如何将DATEDIFF结果转换为小数?

时间:2018-08-21 17:56:49

标签: sql-server stored-procedures casting triggers

希望您能帮助我找到答案,我会解释我的问题。

我正在使用SQL Server 2005中的生物特征标记设备数据库,实际上我正在开发额外的计算时间软件,因此我正在使用2个不同的数据库(mine和生物特征设备数据库)。

我正在尝试计算两个日期之间的小时差,这将是员工使用DATEDIFF在1天之内的2个标记记录,我想将其保存为小数,例如1.5小时,这种方式以后我将能够求和并获得准确的数据。

我正在尝试使用触发器和存储过程来实现这一目标,每插入1条新标记记录,触发器就会执行一次。

触发器唯一要做的就是执行我的存储过程,这时一切正常,唯一的问题是我将DATEDIFF函数转换为十进制。

这是我的触发器:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tri_marcas_ins] 
ON [dbo].[Marcas]  
AFTER INSERT
AS
     DECLARE @codigo VARCHAR(10);
     DECLARE @fecha DATETIME;

     SELECT @codigo = i.Codigo 
     FROM inserted i;

     SELECT @fecha = i.Fecha 
     FROM inserted i;

BEGIN
    EXEC dbHorasExtra.dbo.calculohoras @fecha,@codigo;
END

这是我的存储过程脚本代码:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[calculohoras] 
    @fecha DATETIME, 
    @codigo VARCHAR(10) 
AS
BEGIN
    DECLARE @fechainicial DATETIME;
    DECLARE @fechafinal DATETIME;
    DECLARE @horas DECIMAL(6,2);
    DECLARE @createdat VARCHAR(255);
    DECLARE @updatedat VARCHAR(255);
    DECLARE @codigoemp VARCHAR(255);

    BEGIN
        SET @codigoemp = (SELECT id 
                          FROM nempleados 
                          WHERE codempleado = @codigo)
    END

    SELECT fecha 
    FROM Reloj_3216R.[dbo].Marcas 
    WHERE Codigo = @codigo 
      AND DATEPART(YEAR, fecha) = DATEPART(YEAR, @fecha) 
      AND DATEPART(MONTH, fecha) = DATEPART(MONTH, @fecha) 
      AND DATEPART(DAY, fecha) = DATEPART(DAY, @fecha);

    IF @@ROWCOUNT >= 1
    BEGIN
        SET @fechainicial = (SELECT MIN(fecha) 
                             FROM Reloj_3216R.[dbo].Marcas 
                             WHERE Codigo = @codigo 
                               AND DATEPART(YEAR, fecha) = DATEPART(YEAR, @fecha) 
                               AND DATEPART(MONTH, fecha) = DATEPART(MONTH, @fecha) 
                               AND DATEPART(DAY, fecha) = DATEPART(DAY, @fecha)
    )

    SET @fechafinal = (SELECT MAX(fecha) 
                       FROM Reloj_3216R.[dbo].Marcas 
                       WHERE Codigo = @codigo 
                               AND DATEPART(YEAR, fecha) = DATEPART(YEAR, @fecha) 
                               AND DATEPART(MONTH, fecha) = DATEPART(MONTH, @fecha) 
                               AND DATEPART(DAY, fecha) = DATEPART(DAY, @fecha)
        )
    END
    ELSE
        RETURN

    SELECT * 
    FROM horas 
    WHERE codempleado = @codigo 
      AND DATEPART(YEAR, fecha) = DATEPART(YEAR, @fecha) 
      AND DATEPART(MONTH, fecha) = DATEPART(MONTH, @fecha) 
      AND DATEPART(DAY, fecha) = DATEPART(DAY, @fecha)

    IF @@ROWCOUNT > 0
        RETURN
    ELSE
    BEGIN
        SET @updatedat = GETDATE();
        SET @createdat = GETDATE();
        SET @horas = 
        (
            DATEDIFF(MINUTE,@fechafinal, @fechainicial)/60
        )
        --INSERT INTO horas (codempleado,fecha,horas,created_at,updated_at) VALUES(@codigoemp,@fechafinal,@horas,@createdat,@updatedat);
    END
END

对不起,如果我没有正确询问,我会提供您询问的任何信息!泰语为您提供帮助!

更新: @horas十进制(2,2)更改为@horas十进制(6,2),解决了该问题!非常感谢!

2 个答案:

答案 0 :(得分:0)

正如您已经了解的那样,触发器一定不能只期待一条新记录。要为每个新记录执行存储过程,您将必须使用如下游标:

ALTER TRIGGER [dbo].[tri_marcas_ins] 
ON [dbo].[Marcas]  
AFTER INSERT
AS
BEGIN
     DECLARE @codigo VARCHAR(10);
     DECLARE @fecha DATETIME;

     DECLARE insertedcur CURSOR FAST_FORWARD FOR
       SELECT Codigo, Fecha FROM inserted;

    OPEN insertedcur;

    FETCH NEXT FROM insertedcur INTO @codigo, @fecha;

    WHILE @@FETCH_STATUS = 0
    BEGIN
      EXEC dbHorasExtra.dbo.calculohoras @fecha,@codigo;
      FETCH NEXT FROM insertedcur INTO @codigo, @fecha;
    END

    CLOSE insertedcur;
    DEALLOCATE insertedcur;
END

可以稍微简化您的存储过程,但是即使将@horas变量更改为decimal(6,2),结果也将始终是整数,因为DATEDIFF返回一个整数,而{{ 1}}也是一个整数。要解决此问题,请除以60。您的过程可能如下所示:

60.0

答案 1 :(得分:0)

我将按照OP的建议将评论发布为答案

尝试declare @horas decimal(6,2);您使用declare @horas decimal(2,2);只能从0.00到0.99 – Horaciux 2小时前