SQL Server SELECT查询中括号的角色?

时间:2010-06-25 15:43:32

标签: sql sql-server sql-server-2005 sql-server-2008

以下查询在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)

真实表格会出现同样的问题:在某些情况下,查询不会返回任何结果,如果您进行一些细微的更改,例如删除空格或回车符,它会再次起作用...... < / p>

我认为查询中可能存在问题,因为括号中的SELECT可能会被解释为表达式而不是子查询,如this page中所示。但这应该至少会返回一个错误。

我错过了什么吗?

编辑26/06/2010 :我运行了一些分析会话,结果如下。

对于上面的查询,事件序列为:

  • 异常(错误:208,无效的对象名称)
  • SQL:BatchStarting
  • SQL:StmtStarting
  • SQL:BatchCompleted

对于没有括号的查询:

  • 例外(错误:208)
  • SQL:BatchStarting
  • SQL:StmtStarting
  • 例外(错误:208)
  • 用户错误消息(无效的对象名称't​​his_table_does_not _exist')
  • SQL:BatchCompleted

对于有效的查询:

  • SQL:BatchStarting
  • SQL:StmtStarting
  • Showplan All
  • SQL:StmtCompleted事件
  • SQL:BatchCompleted

我还使用真正的表运行了一个查询,导致我出现同样的问题。事件的顺序是:

  • SQL:BatchStarting
  • SQL:StmtStarting
  • SQL:BatchCompleted

没有早期“例外”=&gt;这些表存在。 没有“SQL:StmtCompleted”=&gt;这意味着发生了错误,我看不出为什么不会引发此事件的任何其他原因。 没有“Showplan All”=&gt;这意味着错误发生在计算执行计划之前(或之后)。它可能是由cte和括号组合引起的。

我将在下周提出微软支持的问题。

2 个答案:

答案 0 :(得分:3)

所以,根据我之前对原始问题的评论,我简化了sql。

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

这似乎给了我们相同的行为。然后我跑了一丝。活动类:

  • SQL:批量启动
  • SQL:批处理已完成
  • 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行的记录集。但是没有计划 - 可能不需要b / c计划,因为没有涉及数据库对象。

所以,为了弄乱我的想法,我尝试了一下:

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错误。它当然似乎与cte和括号有关。我试着谷歌搜索提到它,但没有找到任何东西。这将在下一次本地PASS会议上给我一些讨论。对不起,我必须添加的情况是混乱。如果我学到了什么,我肯定会把它发布在这里!


更新时间:2010-06-26 10:09 CST 我去了Microsoft Connect试图找到这个列为一个问题。我无法找到cte 208或cte invalid object周围的东西。老实说,我不知道另一个可以检查sql server的错误列表网站。我也尝试过搜索Microsoft支持,再次搜索Google。

答案 1 :(得分:0)

从 microsoft doc https://docs.microsoft.com/en-us/sql/t-sql/language-elements/set-operators-union-transact-sql?view=sql-server-ver15 看来,带括号的选择只是联合解析器中的一个特例。我怀疑您是否可以将其用作常规选择。