错误消息“通过聚合或其他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,其规范仅在小节标题中使用了“设置操作”一词,因此在标题中使用了“设置操作”一词。数据分配部分。但是,在快速搜索错误消息之后,我看到了一些示例,这些示例SELECT似乎没有涉及任何分配。

基于SQL Server警告的措辞,我的第二个想法是隐含set的数学含义。但是,我不认为SQL中的聚合严格来说是一种设置操作。即使SQL Server团队将其视为设置操作,将“设置”一词用大写字母的目的是什么?

在谷歌搜索时,我注意到一条SQL Server错误消息:

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

在相同情况下,相同的“设置操作”一词只能指代IDENTITY_INSERT属性的分配,这使我回到了最初的想法。

谁能阐明这个问题?


我一直以为这意味着对一组行进行操作。
马丁·史密斯

@MartinSmith我不这么认为,因为SET总是在全帽像关键字
JNK

@JNK-是的,考虑到这一点,我认为还必须发出其他一些非聚合操作来发出该警告,所以我想我们是否能找出答案可能就可以了!
马丁·史密斯

SELECT * FROM sys.messages WHERE text LIKE '%SET operation%'给出了另外3个似乎也都表示SET关键字的结果。
马丁·史密斯

我做了更多的搜索,它实际上可能是指数学运算中的集合操作。我在SS 2k文档中找到了很多引用和和的set operations引用,但是在任何一种情况下我都找不到错误。我认为这可能是遗留的错误消息。UNIONINTERSECTEXCEPTNULL
JNK 2012年

Answers:


13

我只是在浏览SQL-92规范,看到一段让我想起了这个问题的文章。

实际上,针对这种情况有如下规定的警告

b)否则,将TX设为单列表,该表是将应用于<value expression>T的每一行并消除空值的结果。如果消除了一个或多个空值,则引发完成条件:warning-在set function中消除空值

我假定SETSQL 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更加遵循标准

更长:

如今,该消息由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 2012年

令人遗憾的是,任何比SQL Server 7.0都旧的文档似乎在任何地方都不在线。
马丁·史密斯

1
例如(很难找到的东西这个老):kbalertz.com/Feedback.aspx?kbNumber=149921/EN-US
GBN

1
尽管实际上看起来该消息的SQL Server 7.0版本只是警告:从聚合中消除了空值。SET operation直到2000
马丁·史密斯

2

警告的另一面指的是“设置”操作,而不是“设置”操作-在我看来,这是一个消息错误-例如,它也具有窗口功能:

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 2012年

那叫做“聚合部分”吗?我当然知道您的意思,但是它们是不同的操作-例如,比较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 2012年

好的-从SS文档中了解您的意思
Jack Douglas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.