SQL Server SELECT 查询中括号的作用是什么?

6

以下查询在SQL Server 2008(SP1测试通过)中没有返回结果也没有错误,您可以针对任何数据库运行它,甚至是master:

WITH computed_table (id) AS
(
    SELECT id FROM this_table_does_not_exist
)
(SELECT * FROM computed_table)
UNION
(SELECT * FROM another_table_that_does_not_exists)

在 SQL Server 2005 上,因为表不存在而出现错误。 如果删除一些括号,也会出现错误:
WITH computed_table (id) AS
(
    SELECT id FROM this_table_does_not_exist
)
SELECT * FROM computed_table
UNION
(SELECT * FROM another_table_that_does_not_exists)

同样的问题也会出现在真实的表中:有时候查询不返回任何结果,如果你做一些微小的更改,比如删除一个空格或回车,它就能再次工作了...
我认为可能存在查询问题,因为括号中的SELECT可能被解释为表达式而不是子查询,就像这个页面所示。但至少应该返回一个错误。
我有什么遗漏吗? 编辑 26/06/2010:我运行了一些分析会话,以下是结果。
对于上面的查询,事件序列如下:
  • 异常(错误:208,无效的对象名称)
  • SQL:BatchStarting
  • SQL:StmtStarting
  • SQL:BatchCompleted
对于没有括号的查询:
  • 异常(错误:208)
  • SQL:BatchStarting
  • SQL:StmtStarting
  • 异常(错误:208)
  • 用户错误消息(无效的对象名称'this_table_does_not_exist')
  • SQL:BatchCompleted
对于有效的查询:
  • SQL:BatchStarting
  • SQL:StmtStarting
  • Showplan All
  • SQL:StmtCompleted
  • SQL:BatchCompleted
我还运行了一个与真实表相关的查询,这也给我带来了同样的问题。事件序列如下:
  • SQL:BatchStarting
  • SQL:StmtStarting
  • SQL:BatchCompleted
没有早期的“异常” => 表存在。 没有“SQL:StmtCompleted” => 这意味着发生了错误,我无法看到任何其他原因导致此事件不会被触发。 没有“Showplan All” => 这意味着错误发生在(或在)执行计划计算之前。它可能由cte和括号的组合引起。
我将在下周向Microsoft支持提出问题。

你尝试过将"select *"改为实际的列名吗? - DForck42
1
多好的问题啊!首先,在2008年,第二个语句也会出错。此外,我没有看到UNION语句与奇怪的行为有任何关系,因为删除UNION和第二个SELECT似乎并不会改变结果。有趣的一点是-当使用第一个语句,并要求一个预估执行计划时,我根本没有得到计划。我现在要运行一个跟踪。回头见。 - Jeff Maass
你是否也会发布所提到的代码:“我还运行了一个使用真实表格的查询,这也导致了相同的问题。” 另外,出于纯好奇心,您是否将此视为开发/生产问题的阻碍?如果是这样,解决方法似乎是不遵循cte,然后括号模式。 - Jeff Maass
我在周一向微软提出了这个问题。今天他们将其归类为一个错误。目前还没有解决的截止日期,可能会在服务包或以后的版本中修复。他们确认,在使用公共表达式之后加括号并没有任何建议,但这是一种有效的解决方法。 - Alban Fonrouge
1
太好了!它现在在微软连接中吗?那么,我的回答是一个错误是否可以作为这个问题的被接受的答案? - Jeff Maass
@MaasSql - 看起来现在已经修复了。相关的连接项目在这里 - Martin Smith
2个回答

3

因此,根据我之前对原问题的评论,我稍微简化了SQL语句。

WITH computed_tabled AS
(
    SELECT id FROM this_table_does_not_existd
)
(SELECT id FROM computed_tabled)

这似乎给了我们相同的行为。然后我运行了一次跟踪。事件类别:
  • SQL:Batch Starting
  • SQL:Batch Completed
  • SQL:StmtStarting
  • SQL:StmtCompleted
  • Showplan All
  • Showplan XML
我捕获到的是意外的:
  • SQL:BatchStarting
  • SQL:StmtStarting
  • SQL:BatchCompleted
注意:没有SQL:StmtCompleted,没有计划。所以,接下来,我回到捕获设置,并添加了错误和警告下的每个事件类别。重新运行查询,你知道发生了什么吗?第一个捕获的事件是:
Error: 208, Severity: 16, State: 1

你猜 208 是什么?但是客户端从未看到过错误。

我认为正在发生的是,DBMS中的代码正在说 - 嘿,他们没有要求我们返回任何东西或执行任何操作,那么为什么要费心呢?让我们为更有要求的人释放一些资源。

所以我尝试了这段代码:

--asdfasdf 
( SELECT 1 )

我原以为括号会被解释为表达式,但实际上它们被解释为完整的查询语句(也就是说,客户端确实希望返回一些内容),并返回了一个有1列和1行的记录集。但没有计划——可能是因为没有涉及数据库对象。

所以,为了让我更加困惑,我尝试了这个:

declare @id as integer;
;
WITH computed_table AS
(
    SELECT id FROM this_table_does_not_exist
)
select @id = (SELECT id FROM computed_table)

就像去掉括号一样,这也会产生用户错误信息。

我认为这是一个 MS SQL Server 的 bug。它似乎与 cte 和括号有关。我尝试搜索了一下,但没有找到任何相关的内容。这将成为我在下一个本地 PASS 会议上讨论的话题。抱歉我只能增加混乱。如果我学到了什么,我一定会在这里发布!


更新:2010年06月26日10:09 CST 我访问了Microsoft Connect,试图找到这个问题的列表。我无法找到关于cte 208或cte invalid object的内容。老实说,我不知道还有哪个适用于SQL Server的其他错误列表网站可以查询。我还尝试在Microsoft支持和Google上搜索。


-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接