Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
null
. null
. null
, как если бы это был массив. null
, как если бы это был массив. null
как будто это было значение Throwable. Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null
.
Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Один подход для Oracle:
SELECT val
FROM myTable
UNION ALL
SELECT 'DEFAULT'
FROM dual
WHERE NOT EXISTS (SELECT * FROM myTable)
Или альтернативно в Oracle:
SELECT NVL(MIN(val), 'DEFAULT')
FROM myTable
Или альтернативно в SqlServer:
SELECT ISNULL(MIN(val), 'DEFAULT')
FROM myTable
Они используют то, что MIN()
возвраты NULL
, когда нет никаких строк.
Если Ваш основной запрос, как ожидают, возвратит только одну строку, то Вы могли использовать этот прием:
select NVL( MIN(rate), 0 ) AS rate
from d_payment_index
where fy = 2007
and payment_year = 2008
and program_id = 18
(код Oracle, не уверенный, если NVL является правильной функцией для SQL Server.)
Это было бы, устраняют запрос Select из выполнения дважды и быть лучше для производительности:
Declare @rate int
select
@rate = rate
from
d_payment_index
where
fy = 2007
and payment_year = 2008
and program_id = 18
IF @@rowcount = 0
Set @rate = 0
Select @rate 'rate'
Как насчет этого:
SELECT DEF.Rate, ACTUAL.Rate, COALESCE(ACTUAL.Rate, DEF.Rate) AS UseThisRate
FROM
(SELECT 0) DEF (Rate) -- This is your default rate
LEFT JOIN (
select rate
from d_payment_index
--WHERE 1=2 -- Uncomment this line to simulate a missing value
--...HERE IF YOUR ACTUAL WHERE CLAUSE. Removed for testing purposes...
--where fy = 2007
-- and payment_year = 2008
-- and program_id = 18
) ACTUAL (Rate) ON 1=1
Результаты
Допустимый Уровень Существует
Rate Rate UseThisRate
----------- ----------- -----------
0 1 1
Уровень По умолчанию, Используемый
Rate Rate UseThisRate
----------- ----------- -----------
0 NULL 0
Тестовый DDL
CREATE TABLE d_payment_index (rate int NOT NULL)
INSERT INTO d_payment_index VALUES (1)
Я понял это, и это должно также работать на другие системы также. Это - изменение ответа WW.
select rate
from d_payment_index
where fy = 2007
and payment_year = 2008
and program_id = 18
union
select 0 as rate
from d_payment_index
where not exists( select rate
from d_payment_index
where fy = 2007
and payment_year = 2008
and program_id = 18 )
Один метод сканирования таблицы с помощью левого соединения от значений по умолчанию до фактических данных:
CREATE TABLE [stackoverflow-285666] (k int, val varchar(255))
INSERT INTO [stackoverflow-285666]
VALUES (1, '1-1')
INSERT INTO [stackoverflow-285666]
VALUES (1, '1-2')
INSERT INTO [stackoverflow-285666]
VALUES (1, '1-3')
INSERT INTO [stackoverflow-285666]
VALUES (2, '2-1')
INSERT INTO [stackoverflow-285666]
VALUES (2, '2-2')
DECLARE @k AS int
SET @k = 0
WHILE @k < 3
BEGIN
SELECT @k AS k
,COALESCE(ActualValue, DefaultValue) AS [Value]
FROM (
SELECT 'DefaultValue' AS DefaultValue
) AS Defaults
LEFT JOIN (
SELECT val AS ActualValue
FROM [stackoverflow-285666]
WHERE k = @k
) AS [Values]
ON 1 = 1
SET @k = @k + 1
END
DROP TABLE [stackoverflow-285666]
Дает вывод:
k Value
----------- ------------
0 DefaultValue
k Value
----------- ------------
1 1-1
1 1-2
1 1-3
k Value
----------- ------------
2 2-1
2 2-2
Вы хотите возвратить всю строку? Строка по умолчанию должна иметь значения по умолчанию, или это может быть пустая строка? Вы хотите, чтобы строка по умолчанию имела ту же структуру столбца как рассматриваемая таблица?
В зависимости от Ваших требований, Вы могли бы сделать что-то вроде этого:
1) выполняет запрос и помещенные результаты во временной таблице (или табличная переменная) 2) проверка, чтобы видеть, имеет ли временная таблица результаты, 3) в противном случае возвращают пустую строку путем выполнения избранного оператора, подобного этому (в SQL Server):
select '' as columnA, '' as columnB, '' as columnC from #tempTable
, Где columnA, columnB и columnC являются Вашими фактическими именами столбцов.
Вставьте значения по умолчанию в переменную таблицы, а затем обновите единственную строку этого tableVar в соответствии с фактической таблицей. Если строка найдена, tableVar будет обновлен; если нет, значение по умолчанию остается. Вернуть табличную переменную.
---=== The table & its data
CREATE TABLE dbo.Rates (
PkId int,
name varchar(10),
rate decimal(10,2)
)
INSERT INTO dbo.Rates(PkId, name, rate) VALUES (1, 'Schedule 1', 0.1)
INSERT INTO dbo.Rates(PkId, name, rate) VALUES (2, 'Schedule 2', 0.2)
Вот решение:
---=== The solution
CREATE PROCEDURE dbo.GetRate
@PkId int
AS
BEGIN
DECLARE @tempTable TABLE (
PkId int,
name varchar(10),
rate decimal(10,2)
)
--- [1] Insert default values into @tempTable. PkId=0 is dummy value
INSERT INTO @tempTable(PkId, name, rate) VALUES (0, 'DEFAULT', 0.00)
--- [2] Update the single row in @tempTable with the actual value.
--- This only happens if a match is found
UPDATE @tempTable
SET t.PkId=x.PkId, t.name=x.name, t.rate = x.rate
FROM @tempTable t INNER JOIN dbo.Rates x
ON t.PkId = 0
WHERE x.PkId = @PkId
SELECT * FROM @tempTable
END
Проверьте код:
EXEC dbo.GetRate @PkId=1 --- returns values for PkId=1
EXEC dbo.GetRate @PkId=12314 --- returns default values