我有以下表格:
[位置]
id PK
标题
说明
[地板]
id PK
locationid FK
floorlevel
描述
[室]
id PK
locationid FK
floorid FK
说明
[特征]
id PK
标题
[object_features]
id PK
featureid FK
objectid FK(链接到[locations] .id,[floors] .id或[rooms] .id)
objectype(值1 =位置,2 =楼层,3 =房间)
现在,如果从[位置]删除位置X,我想删除相关的房间和楼层(是的房间也可以直接与位置相关而不是通过楼层),这可以通过级联删除轻松完成。
但是每个不同的对象类型(位置,楼层和房间)也可以有0个或更多个功能,这些功能存储在[object_features]中 这意味着[object_features] .objectid和[object_features] .objecttype可能具有多次相同的值,但与[object_features] .featureid组合时它是唯一的组合。
因此,当删除某个位置时,我还想删除[object_features]中与[locations],[floors]和/或[rooms]中删除的行相关的所有行,因为该位置X被删除。 我觉得我需要在每个表([locations],[floors],[rooms])上添加一些逻辑,以便在删除行时执行操作。我觉得触发器可能会成功,但我不确定这是否是推荐的方法。而且我也不确定如何实现它,一个例子会很棒。
已在此处查看:CASCADE DELETE on two foreign key constraints,但似乎是另一种解决方案。
DDL
CREATE TABLE [dbo].[locations](
[id] [int] IDENTITY(1,1) NOT NULL,
[title] [nvarchar](500) NOT NULL,
CONSTRAINT [PK_homes] PRIMARY KEY NONCLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE TABLE [dbo].[location_floors](
[id] [int] IDENTITY(1,1) NOT NULL,
[locationid] [int] NOT NULL,
CONSTRAINT [PK_location_floors] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[location_floors] WITH CHECK ADD CONSTRAINT [FK_location_floors_locations] FOREIGN KEY([locationid])
REFERENCES [dbo].[locations] ([id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[location_floors] CHECK CONSTRAINT [FK_location_floors_locations]
GO
CREATE TABLE [dbo].[location_rooms](
[id] [int] IDENTITY(1,1) NOT NULL,
[locationid] [int] NOT NULL,
[floorid] [int] NULL,
CONSTRAINT [PK_location_rooms] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[location_rooms] WITH CHECK ADD CONSTRAINT [FK_location_rooms_locations] FOREIGN KEY([locationid])
REFERENCES [dbo].[locations] ([id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[location_rooms] CHECK CONSTRAINT [FK_location_rooms_locations]
GO
CREATE TABLE [dbo].[features](
[id] [int] IDENTITY(1,1) NOT NULL,
[title] [nvarchar](50) NOT NULL,
[createdate] [datetime] NOT NULL,
CONSTRAINT [PK_voorzieningen] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[features] ADD CONSTRAINT [DF_voorzieningen_createdate] DEFAULT (getdate()) FOR [createdate]
GO
CREATE TABLE [dbo].[object_features](
[id] [int] IDENTITY(1,1) NOT NULL,
[objectid] [int] NOT NULL,
[objecttype] [tinyint] NOT NULL,
[featureid] [int] NOT NULL,
[createdate] [datetime] NOT NULL,
CONSTRAINT [PK_location_voorzieningen] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[object_features] ADD CONSTRAINT [DF_location_voorzieningen_createdate] DEFAULT (getdate()) FOR [createdate]
GO
ALTER TABLE [dbo].[object_features] WITH CHECK ADD CONSTRAINT [FK_object_features_features] FOREIGN KEY([featureid])
REFERENCES [dbo].[features] ([id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[object_features] CHECK CONSTRAINT [FK_object_features_features]
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'1=location, 2=floor, 3=room' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'object_features', @level2type=N'COLUMN',@level2name=N'objecttype'
GO
答案 0 :(得分:0)
在由于多个更新路径而不允许DRI的情况下,SQL Server中可以使用INSTEAD OF DELETE
触发器执行级联删除。
以下是按正确顺序执行所需删除的示例。只需在需要级联删除的其他表上按照类似的触发模式。
CREATE TRIGGER tr_location_delete
ON dbo.locations
INSTEAD OF DELETE
AS
SET NOCOUNT ON;
--delete rooms for location
DELETE rooms
FROM dbo.rooms
JOIN dbo.floors ON floors.id = rooms.floorid
JOIN deleted ON deleted.id = rooms.floorid;
--delete floors for location
DELETE floors
FROM dbo.floors
JOIN deleted ON deleted.id = floors.locationid;
--delete location
DELETE locations
FROM dbo.locations
JOIN deleted ON deleted.id = locations.id;
GO