SQL Server:自动为一次插入的所有行添加唯一标识符

时间:2016-08-17 15:59:05

标签: sql sql-server uniqueidentifier

以下SQL Server代码成功计算并插入所有员工的月薪及其staffID号码,并将其插入Tablepayroll

INSERT INTO Tablepayroll (StaffID,Totalpaid)
(SELECT Tabletimelog.StaffID , Tabletimelog.hoursworked * Tablestaff.hourlypay
FROM Tabletimelog 
JOIN Tablestaff ON
Tabletimelog.StaffID = Tablestaff.StaffID)

但是,我希望能够插入一个batchID,这样您就可以在每次运行上面的插入时识别它以及当时插入的记录。这意味着同时计算的所有员工工资单将具有相同的batchID个数字。随后的每个batchID应该增加1。

请参阅下面的图片以获取直观说明。

enter image description here

我认为Select MAX(batch_id) + 1可行,但我不知道如何将其包含在插入语句中。

2 个答案:

答案 0 :(得分:2)

您可以使用子查询使用此查询从当前表中查找最新的batch_id

INSERT INTO TablePayroll (StaffID, TotalPaid, batch_id)
SELECT T1.StaffID
  , T1.HoursWorked * T2.HourlyPay
  , ISNULL((SELECT MAX(batch_id) FROM TablePayRoll), 0) + 1 AS batch_id
FROM TableTimeLog AS T1
INNER JOIN TableStaff AS T2
  ON T1.StaffID = T2.StaffID;

正如您所看到的,我只是将1添加到当前MAX(batch_id),就是这样 顺便说一句,学会使用别名。它会让你的生活更轻松

另一个解决方案是将batch_id作为GUID,这样您就不必创建序列或从当前表中获取MAX(batch_id)

DECLARE @batch_id UNIQUEIDENTIFIER = NEWID();

INSERT INTO TablePayroll (StaffID, TotalPaid, batch_id)
SELECT T1.StaffID, T1.HoursWorked * T2.HourlyPay, @batch_id
FROM TableTimeLog AS T1
INNER JOIN TableStaff AS T2
  ON T1.StaffID = T2.StaffID;

答案 1 :(得分:0)

<强>更新

首先在大表中获取最大值(基于表必须大的表名)可能非常昂贵。特别是如果列batch_id

上没有索引

其次,如果你有竞争性插入,你的解决方案SELECT MAX(batch_id) + 1可能会表现不正确。如果同时并行运行两个插入,@ EvaldasBuinauskas的解决方案无需打开事务和正确的隔离级别也可以导致相同的batch_id

如果您的SQL Server版本为2012或更高版本,则可以尝试SEQUENCE。这至少可以确保没有重复batch_id

创建SEQUENCE

CREATE SEQUENCE dbo.BatchID
    START WITH 1  
    INCREMENT BY 1 ;  
-- DROP SEQUENCE dbo.BatchID
GO  

使用它:

DECLARE @BatchID INT
SET @BatchID =  NEXT VALUE FOR dbo.BatchID;

INSERT INTO Tablepayroll (StaffID,Totalpaid, batch_id)
(SELECT Tabletimelog.StaffID , Tabletimelog.hoursworked * Tablestaff.hourlypay, @BatchID
    FROM Tabletimelog 
        JOIN Tablestaff ON  Tabletimelog.StaffID = Tablestaff.StaffID)

替代SEQUENCE可能是附加表:

CREATE TABLE dbo.Batch (
    ID INT NOT NULL IDENTITY 
        CONSTRAINT PK_Batch PRIMARY KEY CLUSTERED
    ,DT DATETIME
        CONSTRAINT DF_Batch_DT DEFAULT GETDATE()
);

此解决方案甚至可以在旧版本的服务器上运行。

DECLARE @BatchID INT

INSERT INTO dbo.Batch (DT)
    VALUES (GETDATE());

SET @BatchID = SCOPE_IDENTITY();

INSERT INTO Tablepayroll (StaffID,Totalpaid, batch_id)
(SELECT Tabletimelog.StaffID , Tabletimelog.hoursworked * Tablestaff.hourlypay, @BatchID
    FROM Tabletimelog ...

是的,所有这些解决方案都不能保证编号中没有漏洞。这可能发生在事务回滚期间(例如死锁)