Ошибка преобразования даты в TSQL - моя неспособность понять наборы результатов - PullRequest
1 голос
/ 25 января 2011

У меня есть промежуточная область, в которой я пытаюсь проверить данные, проходя несколько итераций проверки.В настоящее время я борюсь с некоторыми проблемами со столбцом nvarchar (50), который пытаюсь преобразовать в дату.

Я знаю о распространенной ошибке плохо сформированных строк, не преобразующих дату, поэтому вотчто я делаю.

SELECT *
  FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1)
 WHERE CAST(DATE_COL AS DATE) < GETDATE()

... это приводит к стандартному «Преобразование не удалось при преобразовании даты и / или времени из символьной строки».

Но вот где все становится страннымдля меня.Если я изменю вышеприведенное выражение на следующее:

SELECT CAST(DATE_COL AS DATE)
  FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1)

... все хорошо, и все, что я сделал, это переместил приведение из условия where в предложение select.Я думаю, что упускаю что-то на фундаментальном уровне.

FWIW, если бы я извлек все записи из STAGE_TABLE без предложения WHERE ISDATE, у меня были бы плохо сформированные строки даты.

Любые идеи с благодарностью!

1 Ответ

3 голосов
/ 25 января 2011

Вы должны обнаружить, что первый запрос объединяет два предложения WHERE в одно и обрабатывает CAST перед ISDATE (сбой).

Второй запрос явно должен сначала обрабатывать WHERE, поэтому CAST никогда не видит неверные данные

Я только что проверил и могу проверить:

create table STAGE_TABLE ( date_col nvarchar(50) )
insert into STAGE_TABLE select 'a'
insert into STAGE_TABLE select '20100101'

Первый запрос

SELECT *
  FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1) X
 WHERE CAST(DATE_COL AS DATE) < GETDATE()

Первый план

  |--Filter(WHERE:(isdate([tempdb].[dbo].[STAGE_TABLE].[date_col])=(1)))
       |--Table Scan(OBJECT:([tempdb].[dbo].[STAGE_TABLE]), WHERE:(CONVERT(date,[tempdb].[dbo].[STAGE_TABLE].[date_col],0)<getdate()))

Второй запрос

SELECT CAST(DATE_COL AS DATE)
  FROM ( SELECT * FROM STAGE_TABLE WHERE ISDATE(DATE_COL) = 1) X

Второй план

  |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(date,[tempdb].[dbo].[STAGE_TABLE].[date_col],0)))
       |--Filter(WHERE:(isdate([tempdb].[dbo].[STAGE_TABLE].[date_col])=(1)))
            |--Table Scan(OBJECT:([tempdb].[dbo].[STAGE_TABLE]))

Похоже, что нет подсказки / опции для исправления первого запроса (поскольку он сворачивается в одно предложение WHERE), но вы можете использовать его для обработки обоих условий за один проход сканирования.

SELECT *
  FROM (SELECT * FROM STAGE_TABLE) X
 WHERE CAST(CASE WHEN ISDATE(DATE_COL) = 1 THEN DATE_COL ELSE NULL END AS DATE) < GETDATE()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...