Мне нужно знать, как вернуть строку по умолчанию, если в таблице нет строк. Какой был бы лучший способ сделать это? Я возвращаю только один столбец из этой таблицы, чтобы получить его значение.
Изменить: это будет SQL Server.
Мне нужно знать, как вернуть строку по умолчанию, если в таблице нет строк. Какой был бы лучший способ сделать это? Я возвращаю только один столбец из этой таблицы, чтобы получить его значение.
Изменить: это будет SQL Server.
В Oracle:
SELECT val
FROM myTable
UNION ALL
SELECT 'DEFAULT'
FROM dual
WHERE NOT EXISTS (SELECT * FROM myTable)
Или, альтернативно:
SELECT NVL(MIN(val), 'DEFAULT')
FROM myTable
Если ваш базовый запрос должен возвращать только одну строку, вы можете использовать этот трюк:
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.)
Это приведет к тому, что запрос выбора будет выполняться дважды и будет лучше для производительности:
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)
Один метод сканирования таблицы с использованием левого соединения от значений по умолчанию:
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) запустите запрос и поместите результаты в таблицу temp (или переменную таблицы) 2) проверьте, имеет ли таблица temp результаты 3) если нет, верните пустую строку, выполнив оператор select, подобный этому (в SQL Server):
select '' as columnA, '' as columnB, '' as columnC from #tempTable
Если columnA, columnB и columnC являются вашими фактическими именами столбцов.
Я понял это, и он также должен работать и для других систем. Это вариация ответа 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 )
Вставьте значения по умолчанию в переменную таблицы, а затем обновите эту таблицу в одной строке с совпадением с вашей фактической таблицей. Если строка найдена, будет обновлен 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