Sql server SQL:是否可以在事务完成之前阻止表插入?

Sql server SQL:是否可以在事务完成之前阻止表插入?,sql-server,triggers,sql-function,check-constraints,sqltransaction,Sql Server,Triggers,Sql Function,Check Constraints,Sqltransaction,TL;DR:我真正的问题是在标题中,是否可以在事务完成之前阻止表插入,也就是说,仅在提交事务之前阻止数据插入 更新:procedes只是一个虚构的示例,可能不是一个好的示例,表明我无法在包含两条语句的事务完成之前找到阻止插入/更新的方法。我只是想知道是否有一种方法可以做到这一点,这个例子有点不相关 这个(可能不好的)例子: 我试图防止在两个表的某些属性被破坏时发生事务,举个简单的例子,假设我想阻止第一个表的值(比如ID)是否已经存在于表2中 create table dbo.tbl1 (

TL;DR:我真正的问题是在标题中,是否可以在事务完成之前阻止表插入,也就是说,仅在提交事务之前阻止数据插入

更新:procedes只是一个虚构的示例,可能不是一个好的示例,表明我无法在包含两条语句的事务完成之前找到阻止插入/更新的方法。我只是想知道是否有一种方法可以做到这一点,这个例子有点不相关

这个(可能不好的)例子:

我试图防止在两个表的某些属性被破坏时发生事务,举个简单的例子,假设我想阻止第一个表的值(比如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中的id值相同

create table dbo.tbl1
(
    id int,
    name varchar(20)
)

create table dbo.tbl2
(
    id int,
    name varchar(20)
)
go
但不幸的是,我尝试定义了一个触发器来阻止它和一个检查约束,但两个约束似乎都无法阻止它

触发器():

检查约束():


如何更新代码以成功阻止事务?是否需要将事务重新定义为同一时间?

尝试在事件发生前将触发器更改为激发,如中所示:

CREATE TRIGGER MyTrigger ON dbo.tbl1
BEFORE INSERT, UPDATE -- this is changed to "BEFORE"
AS

if exists ( select * from tbl2 inner join inserted i on i.id = tbl2.id)
begin
    rollback
    RAISERROR ('Duplicate Data', 16, 1);
end
注:

检查约束只能在表本身内检查


您还应该研究外键,因为这正是解决您遇到的问题的方法。

不,在MSSQLServer中不可能实现您想要的功能,但它可能在PostGres或Oracle中实现

理由第1部分:

理由第2部分:“

因此,在SQLServer中,不可能为多个表的表插入设置一个约束,这些表将在任意事务完成之前阻塞


还值得一提的是,您想要的被称为延迟约束

如果要将相同的值插入到两个表中,为什么不检查传入的值而不插入?这是什么数据库?你的标签到处都是。有什么原因不能在
tbl1
上定义唯一约束吗?@shree.pat18:我的目标是让人们定义涉及两个表的任何事务性语句,但要知道他们不能打破我强加的条件。就像我们定义约束一样,我们不必每次更新表时都记住该逻辑。@mustaccio:ms-sql-server-2005首先将数据插入
tb1
,然后插入
tb2
,因为您已在
tb1
上定义了触发器。当数据插入t-sql中的
tb1
1)时,
tb2
中不会有匹配的记录触发器没有before。有for和after(两者相同)和代替。2) 检查约束只能在表本身内部检查,这是不正确的,因为我的检查约束显然在表外部检查。3) 外键用于确保另一个表中存在其他内容,而不是确保不存在其他内容。
CREATE TRIGGER MyTrigger ON dbo.tbl1
BEFORE INSERT, UPDATE -- this is changed to "BEFORE"
AS

if exists ( select * from tbl2 inner join inserted i on i.id = tbl2.id)
begin
    rollback
    RAISERROR ('Duplicate Data', 16, 1);
end