SQL:是否可以在交易完成之前阻止 table 插入?

SQL: Is it possible to block a table insert just prior to the completion of a transaction?

TL;DR: 我真正的问题在标题中,是否可以在交易完成之前阻止 table 插入,即,仅涉及提交事务之前的数据?

UPDATE: 过程只是一个人为的例子,可能不是一个很好的例子,证明我无法想出一种在包含两个语句的事务完成之前阻止 insertion/update 的方法。我只是想知道有没有办法做到这一点,这个例子有点无关紧要。

(可能不好的)示例:

如果两个 table 中的某些 属性 被破坏,我试图阻止交易发生,举一个简单的例子,假设我想阻止第一个 [=47] 中的一个=]的值(比如ID)已经存在于table 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

因为在交易结束时,第一个 table 的 ID 与 table 中的值相同 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

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

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

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

注意:

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

您还应该学习外键,因为这正是解决您 运行 问题的方法。

不,在 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 中不可能为 table 插入多个 table 的单一约束,这将在任意事务完成之前阻塞。

还值得一提的是,您想要的称为可延迟约束。 See more about that here.