tsql - 在 where 子句中进行日期时间比较后的 MS SQL 算术溢出
问题描述
通过在 ms sql server 2014 上使用日期比较,我遇到了一个奇怪的问题。
SELECT * FROM (SELECT AKTDET.*, DATEDIFF(day,aktdet.Bezahlt_am, getdate()- 50) as datumsdifferenz FROM (SELECT Convert(datetime,AKTDET.von_num - 2.0,121) as [Bezahlt_am], AKT.KENNUNG, AKTDET.* FROM AKT INNER JOIN AKTDET ON AKT.DSN = AKTDET.AKT_DSN Inner JOin FLDART ON AKTDET.Fldart_Dsn = FLDART.DSN WHERE FLDART.Kürzel = 'bezahlt am') AS AKTDET ) AS AKTDET WHERE datumsdifferenz > 0.0
每次都以“Arithmetischer Überlauffehler beim Konvertieren von expression in den datetime-Datentyp”失败。翻译:“将表达式转换为日期时间数据类型时出现算术溢出错误。”
如果我不使用 where 子句,一切都很好。怎么会这样?
SELECT * FROM (SELECT AKTDET.*, DATEDIFF(day,aktdet.Bezahlt_am, getdate()- 50) as datumsdifferenz FROM (SELECT Convert(datetime,AKTDET.von_num - 2.0,121) as [Bezahlt_am], AKT.KENNUNG, AKTDET.* FROM AKT INNER JOIN AKTDET ON AKT.DSN = AKTDET.AKT_DSN Inner JOin FLDART ON AKTDET.Fldart_Dsn = FLDART.DSN WHERE FLDART.Kürzel = 'bezahlt am') AS AKTDET ) AS AKTDET
数据似乎完全正确。所有值都是明显正确的日期值。这是行的示例:
datumsdifferenz Bezahlt_am KENNUNG AKT_DSN
700 2016-12-21 00:00:00.000 340 690837DC-C521-47A7-B845-0B3036CADA07
391 2017-10-26 00:00:00.000 1887 27BC0276-0FAF-4787-BC69-4F7CC8F4D44A
391 2017-10-26 00:00:00.000 1887 27BC0276-0FAF-4787-BC69-4F7CC8F4D44A
392 2017-10-25 00:00:00.000 1890 102CA803-8EA7-48CB-95AE-AA2F8F686715
如果我
select top 80... WHERE datumsdifferenz > 0.0
也使用一切都会正常工作。
如果我使用
select top 90... WHERE datumsdifferenz > 0.0
它会再次抛出这些奇怪的错误。
如果我使用临时表并在之后进行比较它会起作用吗?!
解决方案
我为自己找到了解决方案。如果我使用 where 子句,查询优化器首先使用转换进行全表扫描。
带有 FLDART_DSN = (SELECT TOP 1 DSN FROM FLDART WHERE FLDART.Kürzel = 'bezahlt am') 的子查询将在外部 where 子句之后处理。在这种情况下将扫描整个表。但该表包含没有日期值的数据。这就是为什么在使用外部 where 子句的情况下转换会失败的原因。
解决方案:
SELECT * FROM (SELECT case When von_num < 90000.0 AND von_num > -400000.0 then convert(datetime,VON_NUM,104) END as bezahlt_am, * FROM (SELECT * FROM _TEST WHERE FLDART_DSN = (SELECT TOP 1 DSN FROM FLDART WHERE FLDART.Kürzel = 'bezahlt am')) as test) as test WHERE FLDART_DSN = (SELECT TOP 1 DSN FROM FLDART WHERE FLDART.Kürzel = 'bezahlt am') AND bezahlt_am > GETDATE() - 100.0
SELECT convert(datetime,90000.0,104) -- 2146-05-31 00:00:00.000
SELECT convert(datetime,-40000.0,104) -- 1790-06-26 00:00:00.000
推荐阅读
- java - 当我尝试调用反射方法时抛出异常
- python - 该命令的使用说明(美汤和re.compile)
- ios - 如何检测系统生成的警报视图的动作?
- ios - 在IOS中使用共享
- javascript - 为什么将高分插入我的数据库会导致整个 client.js 无法工作?
- git - GitBash - 如何更好地处理 git multi-repos
- flutter - 如果未登录,如何通过重定向保护会员区?
- laravel - 为什么 Laravel 在刀片中返回 1 作为用户 ID?
- internet-explorer - 网络聊天不适用于 Internet Explorer
- ios - Swift 5,将第一个 VC 锁定为 Potrait 模式,其他 VC 支持所有方向