8

He creado un procedimiento con esta estructura, pero no funciona para el parámetro de entrada datetimeTipo de fecha y hora para el parámetro de entrada en el procedimiento

que ejecuta esta consulta, pero

declare @a datetime 
declare @b datetime 

set @a='2012/04/06 12:23:45' 
set @b='2012/08/06 21:10:12' 

exec LogProcedure 'AccountLog', N'test', @a, @b 

pero SQL Server me tiene esta error

La conversión falló al convertir la fecha y/o hora de la cadena de caracteres.

pero cuando pruebo con esta consulta funciona

exec LogProcedure 'AccountLog',N'test' 

código de procedimiento almacenado:

alter PROCEDURE LogProcedure 
    @TableName VARCHAR(60), 
    @SearchString NVARCHAR(50), 
    @DateFirst DateTime = '', 
    @DateLast DateTime = '' 
AS 
BEGIN 
    SET NOCOUNT ON 

    DECLARE @FinalSQL  NVARCHAR(MAX) 

    SET @FINALSQL = 'SELECT * FROM [' + @TableName + '] where 1=2 ' 

    IF @DateFirst <> '' and @DateLast <> '' 
     set @FinalSQL = @FinalSQL + ' or convert (Date,DateLog) >=  '''[email protected] + ' and convert (Date,DateLog) <='''[email protected] 

    SELECT 
     @FinalSQL = @FinalSQL + ' or [' + SYSCOLUMNS.NAME + '] LIKE N''%' + @SearchString + '%'' ' 
    FROM SYSCOLUMNS 
    WHERE OBJECT_NAME(id) = @TableName 
    AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR','INT','DECIMAL') 
    ORDER BY COLID 

    EXEC(@FinalSQL) 
END 

Esta consulta es verdad también

SELECT * 
FROM AccountLog 
where 1=2 or convert (Date, DateLog) >= '2012/04/06' 
and convert (Date, DateLog) <='2012/08/06' 
+3

No entiendo Stackoverflow más, ¿por qué esta pregunta fue downvoted? es un problema bastante general con una explicación de lo que ha intentado. –

Respuesta

21

Se debe utilizar la ISO -8601 formato para representaciones de fechas en cadena - cualquier otra cosa depende del idioma de SQL Server y de la configuración del formato de fecha.

El formato ISO-8601 para una DATETIME cuando se utiliza sólo la fecha es: YYYYMMDD (sin guiones ni antyhing!)

Para una DATETIME con la porción de tiempo, es YYYY-MM-DDTHH:MM:SS (con guiones, y una T en el porciones de fecha y hora intermedias para separar).

Si desea convertir una cadena a DATE para SQL Server 2008 o posterior, puede usar YYYY-MM-DD (con los guiones) para lograr el mismo resultado. Y no me preguntes por qué esto es tan inconsistente y confuso, simplemente lo es, y tendrás que trabajar con eso por ahora.

Así, en su caso, debería probar:

declare @a datetime 
declare @b datetime 

set @a = '2012-04-06T12:23:45' -- 6th of April, 2012 
set @b = '2012-08-06T21:10:12' -- 6th of August, 2012 

exec LogProcedure 'AccountLog', N'test', @a, @b 

Por otra parte - el procedimiento almacenado tiene un problema, ya que estás concatenar juntos datetime y la cadena en una cadena, pero no estás convirtiendo el datetime a en primer lugar, y también, se está olvidando las citas cercanas en su extracto después de ambas fechas.

Así que cambiar esta línea aquí para esto:

IF @DateFirst <> '' and @DateLast <> '' 
    SET @FinalSQL = @FinalSQL + ' OR CONVERT(Date, DateLog) >= ''' + 
        CONVERT(VARCHAR(50), @DateFirst, 126) + -- convert @DateFirst to string for concatenation! 
        ''' AND CONVERT(Date, DateLog) <=''' + -- you need closing quotes after @DateFirst! 
        CONVERT(VARCHAR(50), @DateLast, 126) + ''''  -- convert @DateLast to string and also: closing tags after that missing! 

Con estos ajustes, y una vez que haya solucionado el procedimiento almacenado que contiene problemas en este momento, va a trabajar.

1

En esta parte de su SP:

IF @DateFirst <> '' and @DateLast <> '' 
    set @FinalSQL = @FinalSQL 
     + ' or convert (Date,DateLog) >=  ''' + @DateFirst 
     + ' and convert (Date,DateLog) <=''' + @DateLast 

que están tratando de concatenar cadenas y datetimes.

Como el tipo datetime tiene mayor prioridad que varchar/nvarchar, el operador +, cuando sucede entre una cadena y una fecha y hora, se interpreta como Además, no como la concatenación, y el motor a continuación, trata de convertir sus partes de cuerdas (' or convert (Date,DateLog) >= ''' y otros) hasta la fecha o valores numéricos. Y falla

Eso no ocurre si se omiten los dos últimos parámetros cuando se invoca el procedimiento, porque la condición se evalúa como falsa y la declaración ofensiva no se ejecuta.

Para modificar la situación, es necesario agregar conversión explícita de las variables de fecha y hora de cuerdas:

set @FinalSQL = @FinalSQL 
    + ' or convert (Date,DateLog) >=  ''' + convert(date, @DateFirst) 
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) 

También tendrá que añadir el cierre de comillas simples:

set @FinalSQL = @FinalSQL 
    + ' or convert (Date,DateLog) >=  ''' + convert(date, @DateFirst) + '''' 
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) + '''' 
Cuestiones relacionadas