【发布时间】:2016-02-05 18:04:43
【问题描述】:
TL;DR:我真正的问题是在标题中,是否可以在事务完成之前阻止表插入,也就是说,只涉及数据就在交易提交之前?
更新:所进行的只是一个人为的示例,可能不是一个好的示例,表明我无法想出阻止插入/更新的方法在包含两个语句的事务完成之前。我只是想知道有没有办法做到这一点,这个例子有点无关紧要。
(可能很糟糕)示例:
如果两个表的某些属性被破坏,我试图阻止事务发生,举个简单的例子,假设如果第一个表的值之一(比如 ID)已经存在于表 2 中,我想阻止。
create table dbo.tbl1
(
id int,
name varchar(20)
)
create table dbo.tbl2
(
id int,
name varchar(20)
)
go
我想失败的事情如下:
begin transaction
insert into tbl1 values(1, 'tbl1_1')
insert into tbl2 values(1, 'tbl2_1')
commit transaction
由于在事务结束时第一个表的 id 值与表 2 中的值相同。
但不幸的是,我尝试定义一个触发器来阻止它和一个检查约束,但似乎都没有阻止它。
触发器(as suggested here):
CREATE TRIGGER MyTrigger ON dbo.tbl1
AFTER INSERT, UPDATE
AS
if exists ( select * from tbl2 inner join inserted i on i.id = tbl2.id)
begin
rollback
RAISERROR ('Duplicate Data', 16, 1);
end
检查约束(as suggested here):
create function dbo.tbl2WithID(@ID int) returns int
as
begin
declare @ret int
select @ret = count(*) from tbl2 where id = @ID
return @ret
end
go
alter table dbo.tbl1
add constraint chk_notbl2withid
check (dbo.tbl2WithID(id) = 0)
go
如何更新我的代码以成功阻止交易?是否需要重新定义交易为同一时间?
【问题讨论】:
-
如果要向两个表中插入相同的值,为什么不检查传入的值并且根本不插入?
-
这是什么数据库?你的标签到处都是。您是否有任何理由无法在
tbl1上定义唯一约束? -
@shree.pat18:我的目标是让人们定义涉及这两个表的任何事务语句,但要知道他们不能破坏我强加的条件。就像我们定义约束一样,我们不必在每次更新表时都记住该逻辑。
-
@mustaccio: ms-sql-server-2005
-
首先您将数据插入
tb1,然后是tb2,因为您已经在tb1上定义了触发器。当数据插入tb1时,tb2中不会有匹配记录
标签: sql-server triggers sql-function check-constraints sqltransaction