SQL Удалить Обновление Ограничение первичного ключа внешнего ключа - PullRequest
1 голос
/ 20 сентября 2011

Допустим, у меня есть таблица, в которой уже есть столбец IsDelete Char (1). Всякий раз, когда я делаю процесс удаления для этой таблицы, Я не делаю фактической команды удаления.

eg. DELETE FROM TableName 

Но я делаю команду Обновить.

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

Так что, если я хочу сделать ссылочную целостность для этих таблиц, я не знаю, как я могу это сделать. Потому что я не делаю фактической команды удаления. Пожалуйста, объясните мне.

Ответы [ 3 ]

2 голосов
/ 20 сентября 2011

Проверьте это декларативное решение, протестированное с 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 голос
/ 20 сентября 2011

Если вы не хотите, чтобы записи удалялись из таблицы, измените права на таблицу, чтобы никто, кроме sys_admin, не мог ее удалить.

Часто при добавлении столбца IS_Deleted лучше всего переименовать таблицу, а затем создать представление со старым именем таблицы, которое выбирает только активные записи.Это предотвратит взлом вашего кода.

Если вы хотите, чтобы происходило обновление, если вы удаляете таблицу, это делается с помощью триггера.В SQL Server триггеры работают на весь пакет, поэтому убедитесь, что триггер может обрабатывать несколько удалений строк.

0 голосов
/ 20 сентября 2011

Во-первых, лучше использовать 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])
...