【问题标题】:SQL Server Unable to convert a string to a date in a where clause (Code 241)SQL Server 无法将字符串转换为 where 子句中的日期(代码 241)
【发布时间】:2017-12-06 07:53:45
【问题描述】:

我有一个查询,它从 char 字段中剪切出一个子字符串并返回一个日期。 它有效:

select 
    ujp_jobid, ujp_lfdnr,
    isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date, getDate())) para_date,
    datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate())), convert(date,getDate())) datedif
from 
    uno_jobpara 
where 
    ujp_jobid between 0 and 30000 
    and ujp_paraname = 'P_PGENDE' 

结果是:

1   6   2017-11-28  8
2   372 2017-05-06  214
3   84  2017-05-01  219

...

我首先尝试使用 datedif 部分作为 where 子句:

...
and ujp_paraname = 'P_PGENDE' 
    and datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate()) ), convert(date,getDate())) > 0

服务器突然报错:

[代码:241,SQL 状态:S0001] Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit。
(粗略翻译:将字符串转换为日期和/或时间时出错)

不太清楚为什么会这样,但我猜是服务器尝试首先检查 where 条件并认为它可能会遇到错误。

但是我试图把所有的都放在另一个选择中:

select 
    ujp_jobid, ujp_lfdnr, para_date, datedif
from 
    (select 
         ujp_jobid, ujp_lfdnr,
         isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date,getDate()) ) para_date,
         datediff(day, isnull(convert(date, substring(ujp_parawert, charindex(' ', ujp_parawert) + 1,10), 104), convert(date, getDate()) ), convert(date, getDate())) datedif
     from 
         uno_jobpara 
     where 
         ujp_jobid between 0 and 30000 
         and ujp_paraname = 'P_PGENDE') as tt
where 
    tt.datedif > 0;

同样的错误?!为什么,以及如何告诉 SQL Server 先运行子查询?我真的需要临时表吗?

TIA

【问题讨论】:

  • 您使用的是哪个版本的 SQL Server? SELECT @@VERSION
  • Microsoft SQL Server 2016 (SP1-GDR) (KB4019089) - 13.0.4206.0 (X64) Jul 6 2017 07:55:03 版权所有 (c) Microsoft Corporation Standard Edition (64-bit) o​​n Windows Server 2012 Datacenter 6.2 (Build 9200: ) (Hypervisor)

标签: sql-server string date substring


【解决方案1】:

首先检查是否所有已解析的字符串都可以转换为 DATE。 由于您使用的是 SQL Server 2016,您可以使用TRY_CONVERT 来测试是否可以转换它们。

SET DATEFORMAT dd.mm.yyyy; -- This format is equivalent to format 104

SELECT 
    ujp_jobid, ujp_lfdnr,
  , substring(ujp_parawert, charindex(' ', ujp_parawert) + 1, 10)
WHERE
  TRY_CONVERT(DATE, SUBSTRING(ujp_parawert, CHARINDEX(' ', ujp_parawert) + 1,10)) IS NULL

检查你得到的记录,那些记录不能转换。

如果有,你必须决定NULLs 是否可以接受。

  • 如果是,请使用TRY_CONVERT() 而不是CONVERT/CAST
  • 如果 NULL 不可接受,则必须修改表达式以处理所有可能的变化。

如果您必须修改表达式,DATEFROMPARTS(year, month, day) 也很有用。

【讨论】:

    【解决方案2】:

    这看起来不像是用临时表解决的问题。 首先,我会避免使用 convert(date,getdate()) 因为它将 getdate() 转换为字符串并再次转换回来,希望格式适合。我会使用 cast(getdate() 作为日期)。 其次,如果您真的向下滚动到最后,问题也应该发生在您的内部查询中。 您可以使用类似 '[0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][ 来测试子字符串是否有效0-9]' 问候,曼弗雷德

    【讨论】:

    • 为什么CONVERT(DATE, GETDATE())会分两步转换?您有任何消息来源支持这一说法吗?
    • 我改变了演员阵容——同样的错误,然后我添加了 ujp_parawert like '%[0-9][0-9].[0-9][0-9].[0-9] [0-9][0-9][0-9]%' 到内部查询 - 同样的错误:-(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多