2011-09-20 85 views
1

假設我有一個已經包含'IsDelete Char(1)'列的表。 每當我對這個表進行刪除處理時,我不會做出實際的刪除命令。SQL刪除更新外鍵主鍵約束

eg. DELETE FROM TableName 

但我做了更新命令。

eg. UPDATE TableName SET IsDelete = '1' ..... 

所以,如果我想爲這個表做參照完整性,我不知道如何做到這一點。 因爲我沒有做出實際的刪除命令。 請解釋我。

回答

0

首先,最好使用bit數據類型爲IsDelete列。

至於參照完整性,您可以使用REFERENCES以及不使用IsDelete列。我沒有看到任何問題。

加盟申請表,你可以使用:

SELECT * 
FROM tbl1 
    JOIN tbl2 ON tbl1.id=tbl2.id 
        and tbl1.IsDelete=0 
        and tbl2.IsDelete=0 

編輯

至於部門和員工。

在現實生活中,關閉部門並不意味着解僱員工。通常情況下,您需要先將員工移至其他部門(或解僱他們),然後關閉部門。在這種情況下,FOREIGN KEYS不會有任何問題。

但是在現實生活中,經常發生這樣的情況,部門首先關閉,然後管理層認爲如何處理人員。

在這種情況下,如果您有以下參考,您仍然不會有任何問題。

ALTER TABLE [Employees] WITH CHECK ADD CONSTRAINT [FK_Employees_Departments] FOREIGN KEY([Department_id]) 
REFERENCES [Departments] ([Department_id]) 
+0

我想說的是讓我們假設有2個表叫做Department和Employee。兩個表都有IsDelete列。所以,如果我首先刪除部門「例如更新部門設置Department.IsDelete = 1其中....」。如果已刪除部門已存在於員工,它可能發生打破部門和員工之間的參照完整性。所以在這種情況下,我該如何做出參照完整性約束。因爲我不想編寫這麼多的代碼來檢查。 –

+0

查看Bogdan Sahlean的回答,他舉了一個很好的例子。 –

+0

@MyatThu我編輯了我的答案。 –

2

檢查與SQL Server測試了這個聲明溶液(見源代碼註釋):

CREATE TABLE dbo.SalesOrder 
(
    SalesOrderID INT IDENTITY(1,1) 
    ,OrderDate DATETIME NOT NULL 
    ,IsDeleted CHAR(1) NOT NULL DEFAULT 'N' 
    ,CONSTRAINT PK_SalesOrder PRIMARY KEY (SalesOrderID) 
    ,CONSTRAINT CK_SalesOrder_IsDeleted CHECK(IsDeleted IN ('Y','N')) 
); 

CREATE TABLE dbo.SalesOrderDetail 
(
    SalesOrderDetailID INT IDENTITY(1,1) 
    ,Qty DECIMAL(8,2) NOT NULL 
    ,UnitPrice DECIMAL(8,2) NOT NULL 
    ,IsDeleted CHAR(1) NOT NULL DEFAULT 'N' 
    ,SalesOrderID INT NOT NULL 
); 

--We need this index to create the next foreign key constraint 
CREATE UNIQUE NONCLUSTERED INDEX IUN_SalesOrder_SalesOrderID_IsDeleted 
ON dbo.SalesOrder(SalesOrderID, IsDeleted); 

--If we "delete" (UPDATE dbo.SalesOrder SET IsDeleted = "Y" ...) a row from dbo.SalesOrder table, 
--then this modification (... SET IsDeleted = "Y" ...) will be propagated to dbo.SalesOrderDetail table 
--because of ON UPDATE CASCADE clause 
ALTER TABLE dbo.SalesOrderDetail 
ADD CONSTRAINT FK_SalesOrderDetail_SalesOrder_SalesOrderID_IsDeleted 
FOREIGN KEY (SalesOrderID, IsDeleted) REFERENCES dbo.SalesOrder(SalesOrderID, IsDeleted) 
ON UPDATE CASCADE; 

INSERT dbo.SalesOrder (OrderDate) 
SELECT '20110101' 
UNION ALL 
SELECT '20110202' 
UNION ALL 
SELECT '20110303'; 

INSERT dbo.SalesOrderDetail (Qty, UnitPrice, SalesOrderID) 
SELECT 1,10,1 UNION ALL SELECT 1,11,1 UNION ALL SELECT 1,12,1 
UNION ALL 
SELECT 2,20,2 
UNION ALL 
SELECT 3,30,3 UNION ALL SELECT 3,31,2; 

SELECT * 
FROM dbo.SalesOrder 
SELECT * 
FROM dbo.SalesOrderDetail 

--Test "DELETE"/UPDATE statement 
UPDATE dbo.SalesOrder 
SET  IsDeleted = 'Y' 
WHERE SalesOrderID = 1; 

--Now, we can check SalesOrderDetail rows ([Status] values WHERE [SalesOrderID]=1) 
SELECT * 
FROM dbo.SalesOrder 
SELECT * 
FROM dbo.SalesOrderDetail 

DROP TABLE dbo.SalesOrderDetail;  
DROP TABLE dbo.SalesOrder; 
+0

假設我將您的代碼更改爲FOREIGN KEY(SalesOrderID,IsDeleted)REFERENCES dbo.SalesOrder(SalesOrderID,IsDeleted) ON UPDATE NO ACTION;因爲我想只爲SaleOrder表禁止刪除操作。然後,SaleOrder表是okey,因爲它在刪除時返回外鍵限制消息(SET IsDeleted ='Y')。但不幸的是,SaleOrderDetail無法刪除(SET IsDeleted ='Y')。所以,如果你有其他解決方案,請給我建議。 –

+0

是@Bogdan我已經運行,因爲你告訴UPDATE dbo.SalesOrderDetail SET IsDeleted ='Y'WHERE SalesOrderID = 1;但是我得到消息「UPDATE語句與參考約束衝突」FK_SalesOrderDetail_SalesOrder_SalesOrderID_IsDeleted「衝突發生在數據庫」DBTest_MT「,表」dbo.SalesOrderDetail「中。」 –

+0

如果將FK定義從ON UPDATE CASCADE更改爲ON UPDATE NO ACTION,你會得到那個錯誤。這個新的規範(「更新不行動」)與參照完整性概念本身衝突/矛盾。例如,您不能有兩個'SalesOrderDetail(SalesOrderID = 101; IsDedeleted ='Y'; Qty = 10&SalesOrderID = 101; IsDedeleted ='Y'; Qty = 20)'SalesOrder(SalesOrderID = 101;請將isDeleted = 'N')'。 –

1

如果你不想從表中刪除以往的記錄,然後更改權限表所以除了sys_admin之外,沒有其他人可以刪除。

通常當您添加一個IS_Deleted列時,最好重命名該表,然後創建一個只有選擇活動記錄的舊錶名的視圖。這將防止你的代碼中斷。

如果您希望在桌面上執行刪除操作時發生更新,則通過觸發器完成更新。在SQL Server觸發器上操作整個批處理,因此請確保觸發器可以處理多行刪除。