簡體   English   中英

SQL刪除更新外鍵主鍵約束

[英]SQL Delete Update Foreign Key Primary Key Constraint

假設我有一個已經包含“ IsDelete Char(1)”列的表。 每當我對此表進行刪除處理時,我都不會執行實際的Delete命令。

eg. DELETE FROM TableName 

但是我做了更新命令。

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

因此,如果要對此表進行引用完整性,則不知道如何實現。 因為我不執行實際的刪除命令。 請給我解釋一下。

檢查此聲明性解決方案是否已通過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;

如果您不希望從表中刪除記錄,請更改表的權限,以便除sys_admin之外的任何人都無法刪除。

通常,在添加IS_Deleted列時,最好重命名表,然后使用僅選擇活動記錄的舊表名創建視圖。 這樣可以防止大量代碼被破壞。

如果您希望在表上執行刪除操作后進行更新,則可以通過觸發器來完成。 在SQL Server中,觸發器對整個批次進行操作,因此請確保觸發器可以處理多行刪除。

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

至於引用完整性,可以使用“ REFERENCES ,也可以不使用“ IsDelete列”。 我認為沒有任何問題。

對於聯接表,您可以使用:

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

編輯

至於部門和員工。

在現實生活中,關閉部門並不意味着要解雇雇員。 通常,您需要先將員工轉移到另一個部門(或解雇他們),然后關閉部門。 在這種情況下,外鍵不會有任何問題。

但是在現實生活中,經常會發生這樣的情況:首先關閉部門,然后管理層考慮與人打交道。

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM