1

I got a view named 'FechasFirmaHorometros' defined as

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' )) ) 

And i have a Function named [RespuestaPreguntaHorometrosFecha] defined as

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

I keep getting this message upon hitting the aforementioned function while debugging another stored procedure that uses it

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

Yet i can freely do things like

SELECT DAY(FechaFirma) FROM FechasFirmaHorometros

Why is this happening and how can i solve or work around it?

Adam Porad
  • 14,193
  • 3
  • 31
  • 56
Machinarius
  • 3,637
  • 3
  • 30
  • 53
  • It might be my imagination, but you seem to be calling one function, IdFormularioHorometros(), and describing another, RespuestaPreguntaHorometrosFecha. – Dan Bracuk Jan 23 '14 at 18:02
  • IdFormularioHorometros() is function used in defining the view, that's all. RespuestaPreguntaHorometrosFecha is the one i describe in the second block, the one with the problem – Machinarius Jan 23 '14 at 18:05
  • 1
    @DanBracuk The function `RespuestaPreguntaHorometrosFecha` uses the view `FechasFirmaHorometros`, and that view uses the function `IdFormularioHorometros`. The error is happening in the function `RespuestaPreguntaHorometrosFecha` which is indirectly using the function `IdFormularioHorometros`. – Adam Porad Jan 23 '14 at 18:05
  • Well, what is the data type of RValues? If is not already date or datetime, why not? – Aaron Bertrand Jan 23 '14 at 18:06
  • can `RValues` contain things other than dates? It's unfortunate, but at times SQL Server will optimistically attempt conversions that would be prevented if conditions in the `WHERE` clause should prevent it from needing to – Damien_The_Unbeliever Jan 23 '14 at 18:07
  • RValues is VARCHAR(MAX), it CAN be anything, but the View will restrict it to *just* strings with this format: YYYY-MM-DD – Machinarius Jan 23 '14 at 18:09
  • 1
    No, that's exactly what I was trying to tell you. There's no guarantee that the view's filters (in and of themselves) will prevent SQL server from attempting to convert any and all values contained in that column to `date`, and that's where the error is coming from. – Damien_The_Unbeliever Jan 23 '14 at 18:14

1 Answers1

6

I assume that RValues is a string column of some type, for some reason. You should fix that and store date data using a date data type (obviously in a separate column than this mixed bag).

If you can't fix that, then you can prevent what Damien described above by:

CASE WHEN ISDATE(RValues) = 1 THEN CONVERT(Date, RValues) END AS FechaFirma 

(Which will make the "date" NULL if SQL Server can't figure out how to convert it to a date.)

You can't prevent this simply by adding a WHERE clause, because SQL Server will often try to attempt the conversion in the SELECT list before performing the filter (all depends on the plan). You also can't force the order of operations by using a subquery, CTE, join order hints, etc. There is an open Connect item about this issue - they are "aware of it" and "hope to address it in a future version."

Short of a CASE expression, which forces SQL Server to evaluate the ISDATE() result before attempting to convert (as long as no aggregates are present in any of the branches), you could:

  • dump the filtered results into a #temp table, and then subsequently select from that #temp table, and only apply the convert then.
  • just return the string, and treat it as a date on the client, and pull YEAR/MONTH etc. parts out of it there
  • just use string manipulation to pull YEAR = LEFT(col,4) etc.
  • use TRY_CONVERT() since I just noticed you're on SQL Server 2012:

    TRY_CONVERT(DATE, RValues) AS FechaFirma
    
Community
  • 1
  • 1
Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • Haven't you got a connect issue about this that the answer should also link to? – Damien_The_Unbeliever Jan 23 '14 at 18:15
  • @Damien maybe [this one](http://connect.microsoft.com/SQLServer/feedback/details/361704/sql-processes-where-clause-items-out-of-order-causing-an-error)? Also for the exception with aggregates see http://connect.microsoft.com/SQLServer/feedback/details/690017/ http://connect.microsoft.com/SQLServer/feedback/details/649957/ http://connect.microsoft.com/SQLServer/feedback/details/691535/ – Aaron Bertrand Jan 23 '14 at 18:26
  • I thought you had a general connect issue (maybe it's Erland) that the product shouldn't report errors when (per the standard, and per MS's own "logical processing order" article) the errors don't actually exist in the *actual* data, if processed in logical order. Or I'm misremembering – Damien_The_Unbeliever Jan 23 '14 at 18:26
  • @Damien found it: http://connect.microsoft.com/SQLServer/feedback/details/537419/ – Aaron Bertrand Jan 23 '14 at 18:32
  • 1
    Yeah, that's the badger. And sorry, I tend to blur you and Erland - you're both superb experts, so I tend to forget which of you is dispensing any particular piece of advice. And I know you're both quite active on connect. – Damien_The_Unbeliever Jan 23 '14 at 18:38
  • @Damien no need to apologize, I'm flattered. – Aaron Bertrand Jan 23 '14 at 18:39
  • @AaronBertrand the connect site has been retired/moved: https://feedback.azure.com/forums/908035-sql-server/suggestions/32912431-sql-server-should-not-raise-illogical-errors – ypercubeᵀᴹ Jan 31 '18 at 16:14
  • @ypercubeᵀᴹ Yeah, I know, unfortunately I don't have a six-week window to go update all of the links I've peppered here over the last 6 or 7 years. :-( On sqlblog.org I've prepended all the links with web.archive.org so they can see the archived versions, since I don't have any way to know what moved and how, and what got abandoned, but that's not perfect either because not all of the link formats are recognizable by archive.org... – Aaron Bertrand Jan 31 '18 at 17:04