Как преодолеть ограничения «iif» с помощью подзапросов? - PullRequest
0 голосов
/ 11 октября 2019

У меня есть 2 таблицы (A и B). Я хочу реализовать такую ​​логику в таблице B:

[Bank] AS (iif( Some_Statement,
                (SELECT [Money] FROM [ATM] WHERE [B].[Currency] = [A].[Currency] ),
                [NoMoney]
               )
          )

Я получаю сообщение об ошибке: Subqueries are not allowed in this context. Only scalar expressions are allowed.

Есть ли способ реализовать такую ​​логику при создании таблиц? Это не выглядит сложно.

Ответы [ 2 ]

2 голосов
/ 11 октября 2019

После прочтения обсуждения в комментариях у меня возникает ощущение, что все идет не в ту сторону. Возможно, из-за вашего очень прямого вопроса о IIF() ...

Если я правильно понял, вы попытаетесь добавить вычисляемый столбец в вашу таблицу. Что-то вроде этого:

DECLARE @tblTest TABLE (ID INT IDENTITY
                       ,SomeValue VARCHAR(100)
                       ,[Test] AS IIF(SomeValue IS NOT NULL, CONCAT(SomeValue,'Blah'), 'Default if null'));

INSERT INTO @tblTest(SomeValue) VALUES('Test');
INSERT INTO @tblTest(SomeValue) VALUES(NULL);

SELECT * FROM @tblTest;

Результат

ID  SomeValue   Test
1   Test        TestBlah
2   NULL        Default if null

Теперь вы хотите получить значение для вычисляемого столбца не только из простого скалярного вычисления, но и изстол.

Здесь я постараюсь смоделировать вашу проблему. В следующий раз вам решать сделать это самостоятельно. Предоставление DDL, образцов данных и ожидаемого результата вместе с вашими собственными попытками - лучший шанс получить ожидаемый ответ.

Это таблица B, из которой вы хотите получить значение.
Позже мы попросим 'Test', а не 'xyz'.

CREATE TABLE tblB (ID INT IDENTITY
                  ,SomeResultColumn VARCHAR(100)
                  ,SomeConditionColumn VARCHAR(100));

INSERT INTO tblB(SomeResultColumn,SomeConditionColumn) VALUES('not wanted','xyz')
                                                            ,('wanted','Test');
GO

- это то, что вы пытаетесь сделать, но я прокомментировал это из-за ошибки, которую выget.
--A вычисляемый столбец не допускает SELECT. Это не связано с IIF()

--CREATE  TABLE tblA (ID INT IDENTITY
--                   ,SomeValue VARCHAR(100)
--                   ,[Test] AS IIF(SomeValue IS NOT NULL,(SELECT b.SomeResultColumn FROM tblB b WHERE b.SomeConditionColumn=SomeValue),'Default if null'));
--GO

- но что мы можем сделать - и сообщение об ошибке говорит об этом - предоставить скалярное выражение:
- Скалярная функция именно такая:

CREATE FUNCTION dbo.GetMyComputedColumn(@Condition VARCHAR(100)) 
RETURNS VARCHAR(100) AS 
BEGIN 
    RETURN (SELECT b.SomeResultColumn --You might use `TOP 1` to ensure a scalar result
            FROM tblB b 
            WHERE b.SomeConditionColumn=@Condition); 
END
GO

- Мы можем использовать эту функцию в IIF():

CREATE  TABLE tblA (ID INT IDENTITY
                   ,SomeValue VARCHAR(100)
                   ,[Test] AS IIF(SomeValue IS NOT NULL,dbo.GetMyComputedColumn(SomeValue),'Default if null'));
GO

INSERT INTO tblA(SomeValue) VALUES('Test');
INSERT INTO tblA(SomeValue) VALUES(NULL);

SELECT * FROM tblA;

Результат

ID  SomeValue   Test
1   Test        wanted
2   NULL        Default if null

Должны ли вы сделать это?

Вопрос, если это хорошая идея, является чем-то совершенно другим.

Помимо того факта, что скалярные функции известны как плохие исполнители, главный вопрос: ПОЧЕМУ?

Вам нужно постоянное значение по умолчанию? В этом случае триггер будет лучшим выбором ... Или вы можете напрямую использовать оператор вставки с вычисленным значением. Боюсь, вы смешиваете понятия вычисляемых столбцов и ограничения по умолчанию . Вычисляемый столбец не может быть изменен ...

Если вы хотите вычислять это значение всякий раз, когда вы выбираете данные из этой таблицы, было бы намного лучше использовать VIEW или iTVF, где выпросто присоедините нужное значение к вашему набору результатов.

1 голос
/ 11 октября 2019

Если вы говорите, что хотите получить значение из таблицы «B», ЕСЛИ оно совпадает со значением из вашей основной таблицы «A», и если в «B» нет соответствующего значения, используйте литерал по умолчанию, попробуйте это:

выберите Bank, coalesce ((ВЫБРАТЬ деньги из банкомата, где валюта = A.Currency), «NoMoney») в качестве «Type» из банкомата A, где ....

Если выбор [Деньги] возвращает ноль, будет использоваться литерал «NoMoney».

При необходимости вы можете иметь выбор с обеих сторон объединения, право не обязательно должно быть литералом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...