为什么YEAR因日期转换错误而失败?

Mac*_*ius 1 sql sql-server-2012

我得到了一个名为'FechasFirmaHorometros'的视图定义为

SELECT IdFormulario, 
       CONVERT(Date, RValues) AS FechaFirma 
FROM   dbo.Respuestas 
WHERE  ( IdPreguntas IN (SELECT IdPregunta 
                         FROM   dbo.Preguntas 
                         WHERE 
         ( FormIdentifier = dbo.IdFormularioHorometros() ) 
         AND ( Label = 'SLFYHDLR' )) ) 
Run Code Online (Sandbox Code Playgroud)

我有一个名为[RespuestaPreguntaHorometrosFecha]的函数定义为

SELECT Respuestas.RValues 
FROM   Respuestas 
       JOIN Preguntas 
         ON Preguntas.Label = @LabelPregunta 
       JOIN FechasFirmaHorometros 
         ON FechasFirmaHorometros.IdFormulario = Respuestas.IdFormulario 
WHERE  Respuestas.IdPreguntas = Preguntas.IdPregunta 
       AND YEAR(FechasFirmaHorometros.FechaFirma) = @Anio 
       AND MONTH(FechasFirmaHorometros.FechaFirma) = @Mes

@LabelPregunta VARCHAR(MAX)
@Anio INT
@Mes INT
Run Code Online (Sandbox Code Playgroud)

在调试使用它的另一个存储过程时,我会在遇到上述函数时收到此消息

Conversion failed when converting date and/or time from character string.
Run Code Online (Sandbox Code Playgroud)

然而,我可以自由地做类似的事情

SELECT DAY(FechaFirma) FROM FechasFirmaHorometros
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况,我该如何解决或解决这个问题?

Aar*_*and 5

我认为这RValues是某种类型的字符串列,出于某种原因.你应该使用日期数据类型来修复它并存储日期数据(显然在这个混合包中的一个单独的列中).

如果你无法解决这个问题,那么你可以通过以下方式阻止Damien所描述的内容:

CASE WHEN ISDATE(RValues) = 1 THEN CONVERT(Date, RValues) END AS FechaFirma 
Run Code Online (Sandbox Code Playgroud)

(NULL如果SQL Server无法弄清楚如何将其转换为日期,那么这将成为"日期" .)

您无法通过添加WHERE子句来阻止这种情况,因为SQL Server通常会SELECT在执行过滤器之前尝试在列表中尝试转换(所有这些都取决于计划).您也不能通过使用子查询,CTE,连接顺序提示等来强制执行操作顺序.有一个关于此问题的开放Connect项目 - 他们"了解它"并"希望在将来的版本中解决它 ".

缺少CASE表达式,它迫使SQL Server在尝试转换之前评估ISDATE()结果(只要任何分支中没有聚合),您可以:

  • 将过滤后的结果转储到#temp表中,然后从该#temp表中进行选择,然后仅应用转换.
  • 只需返回字符串,并将其视为客户端上的日期,并将YEAR/MONTH等部分从中拉出
  • 只需使用字符串操作来拉YEAR = LEFT(col,4)等.
  • 使用,TRY_CONVERT()因为我刚刚注意到你在SQL Server 2012上:

    TRY_CONVERT(DATE, RValues) AS FechaFirma
    
    Run Code Online (Sandbox Code Playgroud)