Роли круглых скобок в запросах SQL Server SELECT? - PullRequest
5 голосов
/ 25 июня 2010

Следующий запрос не возвращает результатов и ошибок на 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 на следующей неделе.

1 Ответ

3 голосов
/ 26 июня 2010

Итак, я немного упростил 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 ?Но клиент никогда не видит ошибку.

Я думаю, что происходит из-за того, что код в СУБД говорит - эй, они не просили нас ничего возвращать или делать что-то, так зачем беспокоиться?Давайте высвободим некоторые ресурсы для кого-то более требовательного.

Итак, я попробовал этот фрагмент кода:

--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.Это, конечно, похоже на cte и круглые скобки.Я пытался поискать в Google, но ничего не нашел.Это даст мне возможность поговорить на следующем заседании ПАСЕ.Извините, все, что я должен добавить в ситуацию, это замешательство.Если я что-то узнаю, я обязательно опубликую это здесь!


Обновление: 2010-06-26 10:09 CST Я обратился в Microsoft Connect, чтобы попытаться найти это в списке проблем.,Я не смог найти что-то около cte 208 или cte недействительный объект .Честно говоря, я не знаю другого сайта с перечнем ошибок для сервера sql, который можно было бы проверить.Я также попытался выполнить поиск в службе поддержки Microsoft и, опять же, в Google.

...