Значение 'SET' в сообщении об ошибке 'Нулевое значение устраняется агрегатом или другой операцией SET'

18

Я видел вышеупомянутое сообщение «Предупреждение ANSI» сегодня, когда запускал скрипт коллеги (и я не знаю, какое из многих утверждений вызвало вывод предупреждения).

В прошлом я игнорировал это: я сам избегаю нулей, и поэтому все, что могло бы их устранить, - хорошая вещь в моей книге! Однако сегодня слово «SET» буквально выкрикнуло на меня, и я понял, что не знаю, каково значение этого слова в этом контексте.

Моя первая мысль, основанная на том факте, что это верхний регистр, заключается в том, что он ссылается на SETключевое слово и означает «назначение», как в

UPDATE <table> SET ...

...ON DELETE SET NULL...

SET IDENTITY_INSERT <table> ON

Согласно справке SQL Server, функция «Предупреждения ANSI» основана на стандарте ISO / ANSI SQL-92, в спецификации которого используется только одно использование термина «Операция Set» в заголовке подраздела, следовательно, в случае заголовка в раздел назначения данных. Однако после быстрого поиска сообщения об ошибке я вижу примеры SELECTзапросов , которые, по- видимому, не связаны с назначением.

Моя вторая мысль, основанная на формулировке предупреждения SQL Server, заключалась в том, что подразумевается математическое значение множества. Тем не менее, я не думаю, что агрегация в SQL, строго говоря, является заданной операцией. Даже если команда SQL Server считает это операцией над множествами, какова цель использования слова «множество» в заглавных буквах?

При поиске я заметил сообщение об ошибке SQL Server:

Table 'T' does not have the identity property. Cannot perform SET operation.

Те же слова «операция SET» в том же случае здесь могут относиться только к назначению IDENTITY_INSERTсвойства, что возвращает меня к моей первой мысли.

Кто-нибудь может пролить свет на этот вопрос?

onedaywhen
источник
Я всегда предполагал, что это означало операцию над множеством строк.
Мартин Смит
@MartinSmith Я так не думаю, потому SETчто всегда в заглавных буквах, как ключевое слово
JNK
@JNK - Да, подумав об этом, я предполагаю, что должна быть какая-то другая неагрегированная операция, которая выдает это предупреждение, поэтому я думаю, если мы узнаем, что это может объяснить это!
Мартин Смит
SELECT * FROM sys.messages WHERE text LIKE '%SET operation%'дает 3 других результата, которые, кажется, все также указывают SETключевое слово.
Мартин Смит
Я проделал еще несколько поисков, и это может относиться к операциям над множествами, как в математических множествах. Я нашел много ссылок в документах SS 2k на set operationsссылки на UNIONи INTERSECTи EXCEPT, но я не могу получить ошибку, чтобы придумать NULLни в одном из этих обстоятельств. Я думаю, что это может быть устаревшее сообщение об ошибке.
JNK

Ответы:

13

Я просто просматривал спецификацию SQL-92 и увидел отрывок, который напомнил мне об этом вопросе.

На самом деле, есть предписанное предупреждение для этой ситуации, как указано ниже

б) В противном случае, пусть TX будет таблица из одного столбца, которая является результатом применения <value expression>к каждой строке T и устранения нулевых значений. Если одно или несколько нулевых значений удаляются, то возникает условие завершения: предупреждение - нулевое значение исключается в заданной функции .

Я предполагаю, что SETв сообщении об ошибке в SQL Server содержится ссылка на функцию set этого сообщения об ошибке, хотя я не уверен, почему в нем будут различаться агрегаты и другие функции set, насколько я вижу, что они являются синонимами. Соответствующий бит грамматики ниже.

6.5  <set function specification>

         Function

         Specify a value derived by the application of a function to an
         argument.

         Format

         <set function specification> ::=
                COUNT <left paren> <asterisk> <right paren>
              | <general set function>

         <general set function> ::=
                <set function type>
                    <left paren> [ <set quantifier> ] <value expression> <right paren>


         <set function type> ::=
              AVG | MAX | MIN | SUM | COUNT

         <set quantifier> ::= DISTINCT | ALL
Мартин Смит
источник
9

Быстрый ответ

«Другой SET *, вероятно, связан с более старыми версиями SQL Server.

Я имел обыкновение видеть это больше, когда я работал с SQL Server 6.5 и 7, я уверен, но это было некоторое время. Многие причуды были устранены + SQL Server больше соответствует стандартам

Longer:

В настоящее время сообщение контролируется по SET ANSI_WARNINGSумолчанию ON.
Это относится исключительно к

  • предупреждение генерируется значением NULL в агрегате.
  • происходит тихое усечение при вставке / обновлении полей типа varchar

Один пример:

DECLARE @foo TABLE (bar int NULL);
INSERT @foo VALUES (1), (2), (NULL);

SET ANSI_WARNINGS ON;
SELECT SUM(bar) FROM @foo;
SET ANSI_WARNINGS OFF;

SELECT SUM(bar) FROM @foo;

дает

(3 row(s) affected)
---- -----------
ON   3
Warning: Null value is eliminated by an aggregate or other SET operation.
(1 row(s) affected)
---- -----------
OFF  3
(1 row(s) affected)

Другой пример:

DECLARE @foo TABLE (bar varchar(5) NULL);
SET ANSI_WARNINGS ON;
INSERT @foo VALUES ('123456'); -- error
GO
DECLARE @foo TABLE (bar varchar(5) NULL);
SET ANSI_WARNINGS OFF;
INSERT @foo VALUES ('123456'); -- OK
GO

Лично я игнорирую предупреждение и оставляю SET ANSI_WARNINGS ON из-за других последствий для вычисляемых столбцов и индексированных представлений установки его OFF.

Наконец, может быть триггер или вычисляемый столбец или индексированное представление, генерирующее это предупреждение где-то

ГБН
источник
Формулировка сообщения об ошибке определенно подразумевает, что есть (или была) какая-то неагрегированная операция, которая также могла бы исключить для меня значения NULL.
Мартин Смит
@ Мартин Смит: согласен. Это может быть косвенным, хотя в соответствии с моим (новым) последним утверждением. Или какая-то стратегия оптимизатора, которую можно было бы увидеть в плане
gbn
Позор, что документы для чего-то более старого чем SQL Server 7.0, кажется, нигде не находятся в сети.
Мартин Смит
1
пример (трудно найти старые вещи): kbalertz.com/Feedback.aspx?kbNumber=149921/EN-US
gbn
1
Хотя на самом деле это выглядит так, как будто версия сообщения SQL Server 7.0 была просто предупреждением: нулевое значение исключено из совокупности. , SET operationБит не был добавлен до 2000 года
Мартин Смит
2

Другая сторона предупреждения относится к операциям 'set', а не к операциям 'SET' - для меня это похоже на сообщение об ошибке - например, оно также создается с помощью оконных функций:

select max(foo) over() as max_foo from (values (1), (2), (null)) as t(foo);
/*
max_foo
-------
2
2
2

Warning: Null value is eliminated by an aggregate or other SET operation.
*/
Джек Дуглас
источник
1
Похоже, что это все еще относится к части агрегации, хотяMAX()
JNK
Это называется «частью агрегации»? Я знаю, что вы имеете в виду, конечно, но это разные операции - например, сравнение select max(foo) from (values (1), (2), (null)) as t(foo) where 1=2;сselect max(foo) over() from (values (1), (2), (null)) as t(foo) where 1=2;
Джек Дуглас
2
Это агрегатная функция :) Я считаю, что ошибка относится к MAX(). Я думаю, что ваш второй пример больше касается порядка операций с использованием оконных функций.
JNK
хорошо - посмотрим, что вы имеете в виду из документов СС
Джек Дуглас