【发布时间】:2021-10-23 13:19:16
【问题描述】:
编辑:这个问题基本解决了。我仍在尝试做的事情可能需要不同的方法。
我正在向旧数据库表添加触发器,以便为相关表自动创建新记录。这不是家庭作业。这是我在 SQL Server 2017 上的 DB Fiddle。https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=ed2ed585606da9d69cb63402ea5c0807
例如,父表如下所示。
新记录将从kids 以逗号分隔的列创建(不幸的是,它是旧数据库,无法更改)。我正在使用 SQL Server 2016 中的 string_split 函数将其分成行。例如。当我在上面插入这 5 条记录时,由于我的触发器,这是我在 kids 表中得到的结果,正如预期的那样。
- kids 表的唯一标识符
kidCode是parentID和每个孩子的名字的哈希值。我们假设每个姓氏都是唯一的,每个孩子的名字都是唯一的,并且姓氏可以改变但孩子的名字不能改变。 - 地址、运动和团队字段是可选的,将在创建/更新期间从父母复制到孩子。
- 孩子的加入日期是父记录首次存在的日期。
编辑:我修复了前两个问题。此外,代码现在包含在下面。
CREATE OR ALTER TRIGGER TR_Update_Kids ON [dbo].[parents] AFTER INSERT, UPDATE AS
BEGIN
SET NOCOUNT ON;
IF TRIGGER_NESTLEVEL(OBJECT_ID('TR_Update_Kids','TR')) > 1 RETURN
MERGE INTO [dbo].[kids] AS KidsTable USING
(SELECT CONVERT(VARCHAR(32), HashBytes('SHA2_256', CONCAT(INSERTED.id,'-',TRIM([value]))), 2) AS kidCode,
INSERTED.surname AS surname,
TRIM([value]) AS name,
INSERTED.address AS address,
INSERTED.sports AS sports,
INSERTED.team AS team,
INSERTED.id AS parentID
FROM INSERTED
CROSS APPLY string_split(INSERTED.kids, ',')
) AS KidsInfo
ON KidsTable.kidCode=KidsInfo.kidCode
WHEN MATCHED THEN UPDATE SET
KidsTable.surname = KidsInfo.surname,
KidsTable.address = KidsInfo.address,
KidsTable.sports = KidsInfo.sports,
KidsTable.team = KidsInfo.team
WHEN NOT MATCHED THEN INSERT
(kidCode,surname,name,address,sports,team,age,class,teacher,parentID,join_date)
VALUES
(KidsInfo.kidCode,KidsInfo.surname,KidsInfo.name,KidsInfo.address,KidsInfo.sports,KidsInfo.team,NULL,NULL,NULL,KidsInfo.parentID,GETDATE());
print ('Added trigger to insert/update kids when parents data changes')
END
触发器似乎可以满足我的一些需求,即当您创建新记录时就可以了。当您更新地址、运动或团队时,它也很好。但是,我还有 3 2 个问题。
-
没有形成新的儿童行。当您将新子项添加到父项的逗号分隔字段时,不会为该子项形成新行。 请看小提琴。现在解决了。 -
不更新姓氏 当您更新父母的姓氏时,会为新姓氏添加新记录,但旧记录也会保留在那里。 请看小提琴。现在解决了。 -
需要双向记录更新 需要双向更新,所以我需要为 kids 表创建第二个(类似)触发器,这样当
name、address,sports或team字段被更新,然后传播回父表。surname永远不会从kids表中更新,parentsID永远不会因任何原因而更新。age、class或teacher的更新将独立于parents。 我不知道如何开始第二个触发器,我们将不胜感激。 这个是结合我在很多 stackoverflow 帖子 starting with my previous post 中阅读的内容的结果,我什至不确定我是否正确地执行了这个新触发器。
如果这第三个问题值得单独提问,请告诉我。然后我将接受前两个的答案,然后为第三个提出一个新问题。谢谢!
【问题讨论】:
-
根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或输入到问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。
-
而且你的问题需要是独立的,所以需要在问题中添加触发代码。小提琴很好,但不应该依赖。
-
我个人建议先修复你的设计。您正在存储分隔数据。解决这个问题,然后担心触发器。
-
@Larnu 好吧,那很好,但我无权访问它。该数据库由已运行数十年的专有可执行文件写入。我的任务是为现有数据和由此可执行文件创建的新传入数据生成报告(使用触发器直接在 SQL 中)。
-
另外,您的触发器不起作用的原因是
IF。在您的示例中,拆分后有两条记录,Samuel 和 Taylor,由于 Samuel 已经存在,因此您在IF中输入真实条件,并且永远不会到达ELSE中的INSERT。IF在整个集合上执行,而不是每行。您可以完全删除IF,只需在插入中添加NOT EXISTS检查,或在MERGE中添加WHEN NOT MATCHED条件(不是100% 确定为什么在这里使用合并,当您所做的只是@987654353 @?)
标签: sql sql-server tsql triggers