与*和显式字段列表不同的结果?

时间:2009-05-06 14:29:52

标签: sql sql-server recursion

当我在Sql Server 2005中遇到此行为时,我正在探索another question。此查询将耗尽最大递归:

with foo(parent_id,child_id) as (
    select parent_id,child_id
    from #bar where parent_id in (1,3)
    union all
    select #bar.* -- Line that changed
    from #bar
    join foo on #bar.parent_id = foo.child_id
)
select * from foo

但这样可行:

with foo(parent_id,child_id) as (
    select parent_id,child_id
    from #bar where parent_id in (1,3)
    union all
    select #bar.parent_id, #bar.child_id -- Line that changed
    from #bar
    join foo on #bar.parent_id = foo.child_id
)
select * from foo

这是Sql Server中的错误,还是我忽略了什么?

以下是表格定义:

if object_id('tempdb..#bar') is not null
    drop table #bar

create table #bar (
    child_id int,
    parent_id int
)

insert into #bar (parent_id,child_id) values (1,2)
insert into #bar (parent_id,child_id) values (1,5)
insert into #bar (parent_id,child_id) values (2,3)
insert into #bar (parent_id,child_id) values (2,6)
insert into #bar (parent_id,child_id) values (6,4)

2 个答案:

答案 0 :(得分:5)

修改

我想我知道发生了什么,并且是一个很好的例子,说明为什么要首先避免选择*。

您先使用childId然后使用parentId定义您的表,但CTE Foo需要parentId,然后是childId,

所以基本上当你说选择#bar。*你的说法选择childId,parentId但你把它放入parentId,child。当你自己重新加入时,这会产生一个n级递归表达式。

所以这不是SQL中的错误。

课程的道德:避免选择*并避免头痛。

答案 1 :(得分:-1)

我认为这可能是程序员故意选择作为安全值,因为你有一个联合,并且联合的所有部分必须具有相同数量的字段。我从不在工会中使用select *,所以我不能肯定地说。我试过SQL Server 2008并收到此消息: Msg 205,Level 16,State 1,Line 1 使用UNION,INTERSECT或EXCEPT运算符组合的所有查询在目标列表中必须具有相同数量的表达式。

这似乎支持了我的理论。

选择*是一种在任何产品代码中使用的技术都很差,所以我不明白为什么简单地指定字段会出现问题。