【发布时间】:2021-08-25 19:14:11
【问题描述】:
我正在尝试以事务的形式完成以下 3 个简单任务(即,我需要锁定 old_table 和 new_table 直到该过程完成)。
- 创建新表 (new_table)
- 向 old_table 添加一个触发器,它将对 new_table 的更新排队。
- 从old_table中选择所有数据并返回。
请注意,我希望在单个事务中处理这些。我不能允许在触发器创建和 old_table 上的选择之间插入 old_table(因此触发插入 new_table)。
我目前最接近的尝试是这样,但说实话,我觉得我离用这段代码实现目标还很远。我添加了代码只是为了参考我正在尝试的内容,但我最感兴趣的是非特定答案,这些答案布局如何在事务中完成上述三个命令。
DROP PROCEDURE IF EXISTS dbo.BuildAll;
CREATE PROCEDURE dbo.BuildAll
AS
BEGIN
BEGIN TRANSACTION
DECLARE @TriggerCode VARCHAR(MAX)
CREATE TABLE dbo.new_table
(
status nvarchar(5),
type char(1),
col1 nvarchar(50),
col2 smallint
)
SELECT @TriggerCode = 'CREATE TRIGGER myTrigger
ON dbo.old_table FOR INSERT
AS
DECLARE @col1_new nvarchar(50)
DECLARE @col2_new smallint
SELECT @col1_new = col1 FROM inserted
SELECT @col2_new = col2 FROM inserted
IF @col1_new IS NOT NULL
BEGIN
INSERT INTO new_table (status, type, col1, col2)
SELECt "Q", "A", @col1, @col2 FROM inserted
END'
EXEC(@TriggerCode)
SELECT * FROM old_table
COMMIT
END
【问题讨论】:
-
您的触发器有 MAJOR 缺陷,您似乎认为它会被 每行调用一次 - 事实并非如此。触发器将每条语句触发一次,因此如果您的
INSERT导致此触发器触发插入25 行,您将触发触发器一次 和@987654324 @ 伪表将包含 25 行。您的代码将从Inserted中选择这 25 行中的哪一行?它是不确定的,您将获得任意行,而您将忽略所有其他行。您需要重写触发器以考虑到这一点! -
老实说,这看起来像是一个问题的解决方案,可能会以更好的方式解决,可能使用您还不知道的功能。如果您尝试生成一些时间稳定的数据快照,请考虑临时表或快照隔离;如果您想原子地切换表,请查看
ALTER TABLE SWITCH或在事务中执行sp_rename;如果您需要复制数据,请考虑事务复制。我想不出任何需要或需要使用触发器的上述方法的情况。 -
这看起来很奇怪,可能是an XY problem。概括说明您正在尝试做什么。
-
@Stu 这不是 XY 问题。对于问题陈述,我进行了编辑以增加清晰度。
-
@DaleK 我很抱歉。我怀疑我在您进行更改的同时进行了编辑。我的头现在有点凉了,我已经简化了这个问题。我希望这会有所帮助。
标签: sql sql-server tsql triggers