sql-server - SQL Server 2019 忽略 WHERE 子句?

标签 sql-server string datetime where-clause sql-server-2019

当我尝试运行简单的聚合查询时遇到错误。

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

错误:从字符串转换日期和/或时间时转换失败。

非日期条目应该由 WHERE 子句删除,但这似乎没有发生。我可以在 MAX() 中使用显式的 CASE 语句来解决问题,但如果可以避免的话,我不想破坏查询。如果我使用较低的 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

最佳答案

我会推荐 try_cast() 而不是 isdate():

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

这是一种更可靠的方法:而不是依靠一些启发式来猜测该值是否可以转换为 datetime (如 isdate() 所做的那样),try_cast 实际上尝试进行转换,如果失败则返回 null - 聚合函数 max() 很乐意忽略它。

try_cast()(以及姊妹函数try_convert())是一个非常方便的函数,许多其他数据库都缺少。

关于sql-server - SQL Server 2019 忽略 WHERE 子句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63273984/

相关文章:

sql - 优化 SQL Server 聚合查询

string - 基于字符串调用函数

javascript - 如何仅在 C# asp.net 中将字符串转换为日期

c# - 哪种日期和时间格式与其他平台最兼容?

c++ - 使用 gSOAP 以本地时间而不是 UTC 返回日期时间

sql - 在使用表时更新表中的数据而不锁定表的最佳方法是什么?

c# - 如何将实体从 ASP.NET MVC 站点序列化为 XML?

sql - 恢复数据库 — 错误 RESTORE HEADERONLY 异常终止。

C# string.Format 抛出异常

java - 如何在Java中使用AES算法解密加密的字符串?