SQL删除更新外键主键约束

时间:2011-09-20 05:40:15

标签: mysql sql-server tsql ddl sql-delete

假设我有一张表已包含'IsDelete Char(1)'列。 每当我为这个表做删除过程时, 我没有制作实际的删除命令。

eg. DELETE FROM TableName 

但我制作了更新命令。

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

因此,如果我想为这些表格制作参考完整性,我不知道如何制作它。 因为我没有制作实际的删除命令。 请解释一下。

3 个答案:

答案 0 :(得分: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;

答案 1 :(得分:1)

如果您不希望从表中删除记录,则更改表的权限,以便除sys_admin之外没有人可以删除。

通常,当您添加IS_Deleted列时,最好重命名该表,然后使用仅选择活动记录的旧表名创建视图。这样可以防止很多代码破坏。

如果要在表上执行删除操作,则需要进行更新,这是通过触发器完成的。在SQL Server中,触发器对整个批处理进行操作,因此请确保触发器可以处理多行删除。

答案 2 :(得分: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])