-4

TL; DR:我真正的問題是在標題中,是否有可能在事務完成之前阻止表插入,也就是說只涉及數據,因爲在交易完成之前承諾?SQL:是否可以在事務完成之前阻止表插入?

UPDATE:什麼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中的值相同。

但是不幸的是我試過定義一個觸發器來阻止這個和檢查約束,阻止它。

觸發(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 

我如何更新我的代碼,以成功地阻止交易?我是否需要將交易重新定義爲同一時間?

+0

爲什麼不檢查傳入的值,而不是根本不插入,如果相同的值要插入到兩個表中? –

+0

這是什麼數據庫?你的標籤遍佈整個地方。有什麼理由不能在'tbl1'上定義唯一的約束? – mustaccio

+0

@ shree.pat18:我的目標是讓人們定義涉及這兩個表格的任何交易陳述,但要知道他們無法打破我強加的條件,請放心。就像我們定義約束一樣,每當我們想要更新表時,我們都不必記住那個邏輯。 – user420667

回答

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.

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,因爲這正是解決你遇到的問題。

+0

1)在t-sql中沒有觸發器。有和之後(這是相同的),而不是。 2)檢查約束只能檢查表本身,這是不正確的,因爲我的檢查約束很清楚地檢查它的表之外。 3)foriegn鍵用於當你想確保別的表中存在別的東西時,而不是確保*不存在*。 – user420667

相關問題