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

时间:2015-11-05 02:11:29

标签: sql-server triggers sql-function check-constraints sqltransaction

TL; DR:我的真正问题在于标题,是否可以在事务完成之前阻止表插入,也就是说,只关注数据,因为它可能是在提交交易之前?

更新 :什么程序仅仅是一个人为的例子,可能不是一个好的例子,证明我无法想出阻止插入/更新的方法在完成包含两个语句的事务之前。我只是想知道是否有办法做到这一点,这个例子有点无关紧要。

(可能不好)示例:

如果两个表的某些属性被破坏,我试图阻止事务发生,一个简单的例子假设我想阻止第一个表的值之一(比如ID)已经存在于表2中。

OperationStatusResponse

我想失败的是:

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

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

因为在事务结束时,第一个表的id值与表2中的值相同。

但不幸的是,我已经尝试定义阻止此操作的触发器和检查约束,并且似乎都没有阻止它。

触发器(as suggested here):

begin transaction
    insert into tbl1 values(1, 'tbl1_1')
    insert into tbl2 values(1, 'tbl2_1')
commit transaction

检查约束(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

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

2 个答案:

答案 0 :(得分:0)

尝试更改触发器以在事件之前触发,如:

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

注意:

检查约束只能检查表本身。

您还应该学习FOREIGN KEYS,因为这正是解决您遇到的问题的原因。

答案 1 :(得分:0)

不,你不可能在MSSQLSever中做你想做的事情,但它可能在PostGres或Oracle中。

原因第1部分:It's not possible to insert to two different tables in the same statement.

原因第2部分:“SQL Server [does not] allow constraint violations in a transaction as long as the transaction has not been committed yet.

因此,SQLServer中不可能对多个表的表插入有一个约束,该表将在任意事务完成之前阻塞。

值得一提的是,你想要的是一个可延迟的约束。 See more about that here.