SQL Сервер 2019 игнорирует предложение WHERE? - PullRequest
1 голос
/ 06 августа 2020

Я получаю сообщение об ошибке, когда пытаюсь выполнить простой агрегатный запрос.

SELECT MAX(CAST(someDate as datetime)) AS MAX_DT FROM #SomeTable WHERE ISDATE(someDate) = 1

ОШИБКА: преобразование не удалось при преобразовании даты и / или времени из символьной строки.

Не Записи -date должны быть удалены предложением WHERE, но, похоже, этого не происходит. Я могу обойтись без явного оператора CASE внутри MAX(), но я не хочу взламывать запрос, если я могу этого избежать. Если я использую более низкий COMPATIBILITY_LEVEL, он работает нормально. Если у меня меньше 2 ^ 17 строк, все работает нормально.

-- SQLServer 15.0.4043.16
USE AdventureWorks;
GO
ALTER DATABASE AdventureWorks SET COMPATIBILITY_LEVEL = 150;
GO

-- delete temp table if exists
DROP TABLE IF EXISTS #SomeTable;
GO

-- create temp table
CREATE TABLE #SomeTable (
    someDate varchar(20) DEFAULT GETDATE()
);

-- load data, need at least 2^17 rows with at least 1 bad date value
INSERT #SomeTable DEFAULT VALUES;

DECLARE @i int = 0;

WHILE @i < 17
BEGIN

    INSERT INTO #SomeTable (someDate) SELECT someDate FROM #SomeTable
    SET @i = @i + 1;

END
GO

-- create invalid date row
WITH cteUpdate AS (SELECT TOP 1 * FROM #SomeTable)
UPDATE cteUpdate SET someDate='NOT_A_DATE'

-- error query
SELECT MAX(CAST(someDate as datetime)) AS MAX_DT
FROM #SomeTable 
WHERE ISDATE(someDate) = 1

--ERROR: Conversion failed when converting date and/or time from character string.

-- delete temp table if exists
DROP TABLE IF EXISTS #SomeTable;
GO

1 Ответ

2 голосов
/ 06 августа 2020

Я бы рекомендовал try_cast(), а не isdate():

SELECT MAX(TRY_CAST(someDate as datetime)) AS MAX_DT
FROM #SomeTable 

Это гораздо более надежный подход: вместо того, чтобы полагаться на некоторые эвристические c, чтобы угадать, можно ли преобразовать значение в datetime (как это делает isdate()), try_cast на самом деле пытается преобразовать и возвращает null, если это не удается - какая агрегатная функция max() к счастью игнорирует.

try_cast() (и сестринские функции try_convert()) - очень удобная функция, которая отсутствует во многих других базах данных.

...