使用 IsActive 更新记录
Update record with IsActive
我正在尝试构建一个维度 table,它将通过使用字段 'IsActive' 和 'EffectiveDate'.
来识别当前和历史数据
IsActive of 1 = 活动。
EffectiveDate = 摄取记录的日期。
场景:我有一个包含员工当前视图的现有记录,但是如果有关员工的任何信息发生变化,我想创建一个新的订单项,而不是更新现有记录,更新后的记录变为活跃而之前的记录变为不活跃。
ID
Name
Surname
Age
IsActive
EffectiveDate
1
John
Doe
54
1
2021-01-01
完成对员工数据的更改后,我想按如下方式更新 table:
ID
Name
Surname
Age
IsActive
EffectiveDate
1
John
Doe
54
0
2021-01-01
2
John
Doe
64
1
2021-06-25
我正在使用 'Name'、'Surname' 和 'Age' 的组合来识别唯一记录。我使用这三个字段的原因是因为没有提供其他信息来唯一标识员工。
非常感谢任何帮助。
你可以自己做,但我会先 Temporal Tables 试一试,这几乎正是它们的设计目的。您只需要学习稍微不同的查询语法即可找到在某个时间点或范围内“活跃”的行。
与此同时,我可以分享一个非常简单的示例来说明如何自己执行此操作,但我同意以下评论,即姓名 + 姓氏 + 年龄是一个糟糕的主键,因为这三个主键都可能因任何给定而改变员工(年龄绝对会改变——这就是为什么我们通常存储生日)。我们为什么不 假装 我们在某个地方为每个员工分配一个唯一但无意义的 ID(这种 ID 会出现在他们的访问徽章上或 HR 数据库中的数据中)只是使示例保持简单。
假设您的 table 是:
CREATE TABLE dbo.EmployeeHistoryStuff
(
ID bigint NOT NULL IDENTITY(1,1) PRIMARY KEY,
EmployeeID int,
Name nvarchar(50),
Surname nvarchar(50),
Age tinyint,
IsActive bit NOT NULL DEFAULT (1),
EffectiveDate datetime2(0) NOT NULL DEFAULT sysutcdatetime()
);
我们可以添加一些示例行:
INSERT dbo.EmployeeHistoryStuff(EmployeeID, Name, Surname, Age)
VALUES(1, N'Aaron', N'Bertrand', 29),
(2, N'Teemu', N'Selanne', 31),
(3, N'Bobby', N'Orr', 62),
(4, N'Wayne', N'Gretzky', 55);
现在我们可以创建一个触发器来拦截对 IsActive = 1
之前任何行的任何更新并插入一个新行:
CREATE TRIGGER dbo.InsteadOfEmployeeHistoryStuff
ON dbo.EmployeeHistoryStuff
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @now datetime2(0) = sysutcdatetime();
UPDATE old SET IsActive = 0
FROM inserted AS i
INNER JOIN dbo.EmployeeHistoryStuff AS old
ON i.EmployeeID = old.EmployeeID
WHERE old.IsActive = 1;
INSERT dbo.EmployeeHistoryStuff(EmployeeID, Name, Surname, Age, EffectiveDate)
SELECT EmployeeID, Name, Surname, Age, DATEADD(SECOND, 1, @now)
FROM inserted;
END
GO
现在,如果我们因为一些员工过生日而执行更新:
UPDATE dbo.EmployeeHistoryStuff SET Age += 1 WHERE EmployeeID IN (1,2);
ID
EmployeeID
Name
Surname
Age
IsActive
EffectiveDate
1
1
Aaron
Bertrand
29
False
2021-10-22 13:37:24
2
2
Teemu
Selanne
31
False
2021-10-22 13:37:24
3
3
Bobby
Orr
62
True
2021-10-22 13:37:24
4
4
Wayne
Gretzky
55
True
2021-10-22 13:37:24
5
1
Aaron
Bertrand
30
True
2021-10-22 13:37:30
6
2
Teemu
Selanne
32
True
2021-10-22 13:37:30
然后韦恩想出风头:
UPDATE dbo.EmployeeHistoryStuff SET Surname = N'Schmetzky' WHERE EmployeeID = 4;
ID
EmployeeID
Name
Surname
Age
IsActive
EffectiveDate
1
1
Aaron
Bertrand
29
False
2021-10-22 13:37:24
2
2
Teemu
Selanne
31
False
2021-10-22 13:37:24
3
3
Bobby
Orr
62
True
2021-10-22 13:37:24
4
4
Wayne
Gretzky
55
False
2021-10-22 13:37:24
5
1
Aaron
Bertrand
30
True
2021-10-22 13:37:30
6
2
Teemu
Selanne
32
True
2021-10-22 13:37:30
7
4
Wayne
Schmetzky
55
True
2021-10-22 13:37:35
然后韦恩改变了主意:
UPDATE dbo.EmployeeHistoryStuff SET Surname = N'Gretzky' WHERE EmployeeID = 4;
ID
EmployeeID
Name
Surname
Age
IsActive
EffectiveDate
1
1
Aaron
Bertrand
29
False
2021-10-22 13:37:24
2
2
Teemu
Selanne
31
False
2021-10-22 13:37:24
3
3
Bobby
Orr
62
True
2021-10-22 13:37:24
4
4
Wayne
Gretzky
55
False
2021-10-22 13:37:24
5
1
Aaron
Bertrand
30
True
2021-10-22 13:37:30
6
2
Teemu
Selanne
32
True
2021-10-22 13:37:30
7
4
Wayne
Schmetzky
55
False
2021-10-22 13:37:35
8
4
Wayne
Gretzky
55
True
2021-10-22 13:37:40
9
4
Wayne
Gretzky
55
True
2021-10-22 13:37:40
我的时间有点不对,我会回来修复一下。
您可以使用 Merge 语句作为选项之一,当与源 table (原始 table) 基于条件。
此处要更新现有记录,您不能使用“年龄”列来定义组合中的唯一性,因为新数据集的“年龄”列中的数据发生了变化。
以下是我的复现详情:
- 现有维度员工数据:
- 源数据:
代码:
Create procedure sp_employee
AS
SET NOCOUNT ON;
BEGIN
--update Active flag of existing data
MERGE dim_employee AS Target
USING employee_data AS Source
ON Source.Name = Target.Name
and Source.Surname = Target.Surname
WHEN MATCHED THEN UPDATE SET
Target.IsActive = 0;
--Insert new data (assuming the table has only changed data set)
Insert into dim_employee
select Name, Surname, Age, IsActive, EffectiveDate from employee_data;
End
GO
如果源中有旧记录 table 以及新的更改集,您可以使用以下代码仅插入更改数据集。
Insert into dim_employee
select Name, Surname, Age, IsActive, EffectiveDate from employee_data
except
select distinct a.Name, a.Surname, a.Age, a.IsActive, a.EffectiveDate from employee_data a
inner join dim_employee b on a.Name = b.Name and a.Surname = b.Surname and a.Age = b.Age;
执行存储过程
Exec sp_employee;
执行存储过程后:'John Doe' 的 IsActive 列数据已更新为 0,并且从 employee_data table 插入了 'John Doe' 的新记录.
我正在尝试构建一个维度 table,它将通过使用字段 'IsActive' 和 'EffectiveDate'.
来识别当前和历史数据IsActive of 1 = 活动。
EffectiveDate = 摄取记录的日期。
场景:我有一个包含员工当前视图的现有记录,但是如果有关员工的任何信息发生变化,我想创建一个新的订单项,而不是更新现有记录,更新后的记录变为活跃而之前的记录变为不活跃。
ID | Name | Surname | Age | IsActive | EffectiveDate |
---|---|---|---|---|---|
1 | John | Doe | 54 | 1 | 2021-01-01 |
完成对员工数据的更改后,我想按如下方式更新 table:
ID | Name | Surname | Age | IsActive | EffectiveDate |
---|---|---|---|---|---|
1 | John | Doe | 54 | 0 | 2021-01-01 |
2 | John | Doe | 64 | 1 | 2021-06-25 |
我正在使用 'Name'、'Surname' 和 'Age' 的组合来识别唯一记录。我使用这三个字段的原因是因为没有提供其他信息来唯一标识员工。
非常感谢任何帮助。
你可以自己做,但我会先 Temporal Tables 试一试,这几乎正是它们的设计目的。您只需要学习稍微不同的查询语法即可找到在某个时间点或范围内“活跃”的行。
与此同时,我可以分享一个非常简单的示例来说明如何自己执行此操作,但我同意以下评论,即姓名 + 姓氏 + 年龄是一个糟糕的主键,因为这三个主键都可能因任何给定而改变员工(年龄绝对会改变——这就是为什么我们通常存储生日)。我们为什么不 假装 我们在某个地方为每个员工分配一个唯一但无意义的 ID(这种 ID 会出现在他们的访问徽章上或 HR 数据库中的数据中)只是使示例保持简单。
假设您的 table 是:
CREATE TABLE dbo.EmployeeHistoryStuff
(
ID bigint NOT NULL IDENTITY(1,1) PRIMARY KEY,
EmployeeID int,
Name nvarchar(50),
Surname nvarchar(50),
Age tinyint,
IsActive bit NOT NULL DEFAULT (1),
EffectiveDate datetime2(0) NOT NULL DEFAULT sysutcdatetime()
);
我们可以添加一些示例行:
INSERT dbo.EmployeeHistoryStuff(EmployeeID, Name, Surname, Age)
VALUES(1, N'Aaron', N'Bertrand', 29),
(2, N'Teemu', N'Selanne', 31),
(3, N'Bobby', N'Orr', 62),
(4, N'Wayne', N'Gretzky', 55);
现在我们可以创建一个触发器来拦截对 IsActive = 1
之前任何行的任何更新并插入一个新行:
CREATE TRIGGER dbo.InsteadOfEmployeeHistoryStuff
ON dbo.EmployeeHistoryStuff
INSTEAD OF UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @now datetime2(0) = sysutcdatetime();
UPDATE old SET IsActive = 0
FROM inserted AS i
INNER JOIN dbo.EmployeeHistoryStuff AS old
ON i.EmployeeID = old.EmployeeID
WHERE old.IsActive = 1;
INSERT dbo.EmployeeHistoryStuff(EmployeeID, Name, Surname, Age, EffectiveDate)
SELECT EmployeeID, Name, Surname, Age, DATEADD(SECOND, 1, @now)
FROM inserted;
END
GO
现在,如果我们因为一些员工过生日而执行更新:
UPDATE dbo.EmployeeHistoryStuff SET Age += 1 WHERE EmployeeID IN (1,2);
ID EmployeeID Name Surname Age IsActive EffectiveDate 1 1 Aaron Bertrand 29 False 2021-10-22 13:37:24 2 2 Teemu Selanne 31 False 2021-10-22 13:37:24 3 3 Bobby Orr 62 True 2021-10-22 13:37:24 4 4 Wayne Gretzky 55 True 2021-10-22 13:37:24 5 1 Aaron Bertrand 30 True 2021-10-22 13:37:30 6 2 Teemu Selanne 32 True 2021-10-22 13:37:30
然后韦恩想出风头:
UPDATE dbo.EmployeeHistoryStuff SET Surname = N'Schmetzky' WHERE EmployeeID = 4;
ID EmployeeID Name Surname Age IsActive EffectiveDate 1 1 Aaron Bertrand 29 False 2021-10-22 13:37:24 2 2 Teemu Selanne 31 False 2021-10-22 13:37:24 3 3 Bobby Orr 62 True 2021-10-22 13:37:24 4 4 Wayne Gretzky 55 False 2021-10-22 13:37:24 5 1 Aaron Bertrand 30 True 2021-10-22 13:37:30 6 2 Teemu Selanne 32 True 2021-10-22 13:37:30 7 4 Wayne Schmetzky 55 True 2021-10-22 13:37:35
然后韦恩改变了主意:
UPDATE dbo.EmployeeHistoryStuff SET Surname = N'Gretzky' WHERE EmployeeID = 4;
ID EmployeeID Name Surname Age IsActive EffectiveDate 1 1 Aaron Bertrand 29 False 2021-10-22 13:37:24 2 2 Teemu Selanne 31 False 2021-10-22 13:37:24 3 3 Bobby Orr 62 True 2021-10-22 13:37:24 4 4 Wayne Gretzky 55 False 2021-10-22 13:37:24 5 1 Aaron Bertrand 30 True 2021-10-22 13:37:30 6 2 Teemu Selanne 32 True 2021-10-22 13:37:30 7 4 Wayne Schmetzky 55 False 2021-10-22 13:37:35 8 4 Wayne Gretzky 55 True 2021-10-22 13:37:40 9 4 Wayne Gretzky 55 True 2021-10-22 13:37:40
我的时间有点不对,我会回来修复一下。
您可以使用 Merge 语句作为选项之一,当与源 table (原始 table) 基于条件。
此处要更新现有记录,您不能使用“年龄”列来定义组合中的唯一性,因为新数据集的“年龄”列中的数据发生了变化。
以下是我的复现详情:
- 现有维度员工数据:
- 源数据:
代码:
Create procedure sp_employee AS SET NOCOUNT ON; BEGIN --update Active flag of existing data MERGE dim_employee AS Target USING employee_data AS Source ON Source.Name = Target.Name and Source.Surname = Target.Surname WHEN MATCHED THEN UPDATE SET Target.IsActive = 0; --Insert new data (assuming the table has only changed data set) Insert into dim_employee select Name, Surname, Age, IsActive, EffectiveDate from employee_data; End GO
如果源中有旧记录 table 以及新的更改集,您可以使用以下代码仅插入更改数据集。
Insert into dim_employee select Name, Surname, Age, IsActive, EffectiveDate from employee_data except select distinct a.Name, a.Surname, a.Age, a.IsActive, a.EffectiveDate from employee_data a inner join dim_employee b on a.Name = b.Name and a.Surname = b.Surname and a.Age = b.Age;
执行存储过程
Exec sp_employee;
执行存储过程后:'John Doe' 的 IsActive 列数据已更新为 0,并且从 employee_data table 插入了 'John Doe' 的新记录.