Sql 如何删除FK和所有相关表项?
事实就是这样。Sql 如何删除FK和所有相关表项?,sql,sql-server,tsql,foreign-keys,constraints,Sql,Sql Server,Tsql,Foreign Keys,Constraints,事实就是这样。 有3个表格-州、地区和城市。如果我删除一个名为“法国”的州,我希望属于该州的所有地区和城市也被删除。如何在T-SQL中执行此操作?您可以设置表以进行级联删除,因此您可以从表中删除所有外键的条目。最简单的解决方案是确保在表之间的关系上启用了级联删除 Create Table State ( Code char(2) not null Primary Key , ... ) Create Table Region ( Code varchar(10) not
有3个表格-州、地区和城市。如果我删除一个名为“法国”的州,我希望属于该州的所有地区和城市也被删除。如何在T-SQL中执行此操作?您可以设置表以进行级联删除,因此您可以从表中删除所有外键的条目。最简单的解决方案是确保在表之间的关系上启用了级联删除
Create Table State
(
Code char(2) not null Primary Key
, ...
)
Create Table Region
(
Code varchar(10) not null
, StateCode char(2) not null
, Constraint FK_Region_State
Foreign Key ( StateCode )
References State( Code )
On Delete Cascade
)
Create Table City
(
Name varchar(40) not null
, StateCode char(2) not null
, RegionCode varchar(10) not null
, Constraint FK_City_State
Foreign Key ( StateCode )
References State( Code )
On Delete Cascade
, Constraint FK_City_Region
Foreign Key ( StateCode )
References State( Code )
On Delete Cascade
)
如果由于某种原因无法启用级联删除,则必须通过状态表上的触发器强制执行此规则。(顺便说一句,一个名为法国的“州”?我假设你还没有建立,所以你必须自下而上:先删除城市,然后删除地区,然后删除州
delete from c
from city c
inner join region r
on c.region_id = r.region_id
inner join state s
on r.state_id = s.state_id
where s.state = 'France'
delete from r
from region r
inner join state s
on r.state_id = s.state_id
where s.state = 'France'
delete from s
from state s
where s.state = 'France'
虽然级联删除是一种方式,但我很不舒服设置它。这样做感觉很不安全,所以我从不设置级联删除 我更喜欢用TSQL来做
DELETE FROM Cities
WHERE RegionId IN
(
SELECT Id
From Regions
Where CountryId IN
(
Select Id
From Country
Where Country = 'France'
)
)
然后删除区域
DELETE FROM Regions
Where RegionId IN
(
Select Id
From Country
Where Country = 'France'
)
然后删除国家
DELETE FROM Country
Where Country = 'France'
我知道,但我需要一个更快的方法。正如您提到的术语“级联删除”,我将转到MSDN,阅读相关内容,如果有什么问题,请返回。如中所述,我个人也不喜欢级联删除。和Raj一样,我更喜欢在自己的代码中保留对这些操作的控制。显然,您也希望确保在事务中这样做。我非常同意,级联删除是一件非常危险的事情,可能会导致系统停止。我从不推荐使用它。@HLGEM-封装到具有等效隔离级别的事务中的上述三个查询与级联删除有何不同?@Thomas,它们与级联删除没有任何不同。但是假设您已经在在线商店中实现了级联删除,并且您在配送模式下运行了
delete,其中type='fedex'
。您刚刚丢失了所有旧订单(诚然,您可以从备份中获取它们),但也丢失了尚未进入备份的新订单。这些场景只会让我感到不安。@Raj More-如果删除sp在您删除发货模式时将所有订单炸开,那么您与使用CD是同一条船。正如在删除配送模式时不会包含该逻辑一样,在该场景中也不应启用级联删除。是的,要小心谨慎,但这不是极端主义的关键。例如,不在发票行项目或订单行项目上使用CD是愚蠢的。和任何事情一样,在有意义的地方使用它。触发器或cacade删除都不是一个好主意。如果级联删除一个包含数千或数百万子记录的记录,会发生什么情况?哦,是的,桌子被锁上了,没人能工作。除非您知道记录的数量很小,否则通过cascade delte强制执行此操作是非常糟糕的。此外,如果子记录仍然存在,它就失去了不想删除的想法。这是一件很重要的事情,因为很多时候,子记录的存在告诉您不应该删除父记录。@HLGEM-a.世界上没有成千上万的城市或国家。假设有数以万亿计的行依赖于您的“France”行,您需要删除它。它仍然必须在事务中完成,以保持数据完整性。Cascade Delete所做的一切就是省去了在一个事务中编写多个删除查询的麻烦。@HLGEM-我并不是建议在任何地方都使用CD,但是如果在删除父行时总是希望删除子行,那么Cascade Delete是有意义的。也许对于一万亿行,这可能不是出于性能原因,但不管您是否这样做,都取决于问题、模式和业务规则。