2010-04-12 19 views
5

Uso de SQL Server 2008, Visual Studio 2005, .net 2.0 con SP2 (tiene soporte para nuevos tipos de datos de SQL Server 2008).SQLCLR y DateTime2

Estoy tratando de escribir una función SQLCLR que toma un DateTime2 como entrada y devuelve otro DateTime2. p.ej. :

using System; 
using System.Data.SqlTypes; 
using Microsoft.SqlServer.Server; 

namespace MyCompany.SQLCLR 
{ 
    public class DateTimeHelpCLR 
    { 
     [SqlFunction(DataAccess = DataAccessKind.None)] 
     public static SqlDateTime UTCToLocalDT(SqlDateTime val) 
     { 
      if (val.IsNull) 
       return SqlDateTime.Null; 

      TimeZone tz = System.TimeZone.CurrentTimeZone; 
      DateTime res = tz.ToLocalTime(val.Value); 

      return new SqlDateTime(res); 
     } 
    } 
} 

Ahora, lo anterior compila bien. Quiero que estos SqlDateTimes para asignar a DateTime2 de SQL Server, así que trato de ejecutar este T-SQL:

CREATE function hubg.f_UTCToLocalDT 
(
    @dt DATETIME2 
) 
returns DATETIME2 
AS 
EXTERNAL NAME [SQLCLR].[MyCompany.SQLCLR.DateTimeHelpCLR].UTCToLocalDT 
GO 

Esto da el siguiente error:

Msg 6551, nivel 16, estado 2, Procedimiento f_UTCToLocalDT, línea 1 CREAR FUNCIÓN para "f_UTCToLocalDT" error porque T-SQL y tipos de CLR para el valor de retorno no coinciden.

El uso de DATETIME (en lugar de DATETIME2) funciona bien. Pero prefiero usar DATETIME2 para apoyar la mayor precisión. ¿Qué estoy haciendo algo mal, o es DateTime2 no (totalmente) compatible con SQLCLR?

Respuesta

9

Debe cambiar los tipos de fecha y hora en la firma de su método de función. SQLDateTime asigna a DateTime en la base de datos.

System.DateTime es más preciso y puede ser asignada a DateTime2 (pero por defecto, que va a dejarse caer como un DateTime en la secuencia de comandos de despliegue).

[SqlFunction(DataAccess = DataAccessKind.None)] 
//OLD Signature public static SqlDateTime UTCToLocalDT(SqlDateTime val) 
public static DateTime UTCToLocalDT(DateTime val) { 
    ... 
} 

Luego puede ajustar su script de despliegue para leer.

CREATE FUNCTION [UTCToLocalDT] 
(
    @dt [datetime2] 
) 
RETURNS [datetime2] 
AS 
    EXTERNAL NAME [SQLCLR].[MyCompany.SQLCLR.DateTimeHelpCLR].UTCToLocalDT 
GO 

La ejecución de su función ahora debería darle una salida más precisa.

DECLARE @input DateTime2, @output DateTime2 
SET @input = '2010-04-12 09:53:44.48123456' 
SET @output = YourDatabase.dbo.[UTCToLocalDT](@input) 
SELECT @input, @output 
+2

Gracias por eso. ¿Esta técnica admite pasar y devolver valores NULL? –

+0

¿Cómo puedo modificar una secuencia de comandos de implementación? No hay uno por lo que estoy lejos cuando haces clic derecho y eliges "Implementar" en Visual Studio. El objetivo del atributo SqlFunction es automatizar ese proceso para que pueda elegir implementar desde el menú contextual. – Triynko

+0

Y no ... esto no admite nulos, ya que tendría que usar Nullable , que no parece ser compatible. No se puede implementar incluso en Visual Studio 2010 Ultimate. – Triynko

0

Tenga en cuenta que con "DateTime?" siempre proporciona errores de compilación (incluso en VS 2013 con sql 2012), aunque aparentemente el resultado se puede usar si se selecciona "compilar, implementar" y luego utiliza los archivos en la carpeta obj, editando el archivo generated.sql en la ventana de consulta sql (para usar DateTime2 como parámetro) antes de ejecutarlo para agregarlo al servidor Sql.
El error de compilación es "SQL46010: sintaxis incorrecta cerca"). en \ obj \ Debug \ YourPrjName.generated.sql

(registraría anteriormente como comentario si pudiera.)

Cuestiones relacionadas