Другой результат с * и явным списком полей? - PullRequest
3 голосов
/ 06 мая 2009

Я изучал другой вопрос , когда столкнулся с таким поведением в Sql Server 2005. Этот запрос исчерпал бы максимальную рекурсию:

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 ]

5 голосов
/ 06 мая 2009

Редактировать

Мне кажется, я знаю, что происходит, и это отличный пример того, почему следует избегать выбора *.

Вы определили таблицу сначала с childId, а затем parentId, но CTE Foo ожидает, что parentId, а затем childId,

По сути, когда вы говорите select # bar. * Ваше высказывание select childId, parentId, но вы помещаете это в parentId, child. Это приводит к рекурсивному выражению n-уровня, когда вы снова присоединяетесь к себе.

Так что это не ошибка в SQL.

Мораль урока: избегайте выбора * и избавьте себя от головной боли.

0 голосов
/ 06 мая 2009

Я бы сказал, что программисты, вероятно, сделали это преднамеренным выбором в качестве значения безопасности, потому что у вас есть объединение, и все части объединения должны иметь одинаковое количество полей. Я никогда не использую select * в союзе, поэтому не могу сказать наверняка. Я попробовал на SQL Server 2008 и получил это сообщение: Сообщение 205, уровень 16, состояние 1, строка 1 Все запросы, объединенные с использованием оператора UNION, INTERSECT или EXCEPT, должны иметь одинаковое количество выражений в своих целевых списках.

Кажется, это подтверждает мою теорию.

Выбор * - плохая методика для использования в любом коде продукта, поэтому я не понимаю, почему было бы сложно просто указать поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...