SQL Server 2005 - Каскадное удаление во всех связанных таблицах - PullRequest
1 голос
/ 28 октября 2010
CREATE Table A
(
 AId int ,
 AName varchar(100)
)

CREATE Table B
(
 BId int,
 AId int,
 CId int,
 BName varchar(100)
)

CREATE Table C
(
 CId int,
 CName varchar (100)

)

У «A» есть внешний ключ в «B», а у «C» также есть внешний ключ в B. Оба внешних ключа имеют включенное каскадное удаление.

Внешний ключ: -

/****** Object:  ForeignKey [FK_B_A]    Script Date: 10/28/2010 17:20:16 ******/
ALTER TABLE [dbo].[B]  WITH CHECK ADD  CONSTRAINT [FK_B_A] FOREIGN KEY([AId])
REFERENCES [dbo].[A] ([AId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[B] CHECK CONSTRAINT [FK_B_A]
GO
/****** Object:  ForeignKey [FK_B_C]    Script Date: 10/28/2010 17:20:16 ******/
ALTER TABLE [dbo].[B]  WITH CHECK ADD  CONSTRAINT [FK_B_C] FOREIGN KEY([CId])
REFERENCES [dbo].[C] ([CId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[B] CHECK CONSTRAINT [FK_B_C]
GO

- Пример данных

INSERT INTO A
VALUES (1, 'Ashish')
INSERT INTO A
VALUES (2, 'Sanjay')
INSERT INTO A
VALUES (3, 'Vivek')

INSERT INTO B
VALUES
(1,1,10,'Ashish1')
INSERT INTO B
VALUES
(2,1,11,'Ashish2')
INSERT INTO B
VALUES
(3,1,12,'Ashish3')


INSERT INTO B
VALUES
(4,2,13,'Ashish1')
INSERT INTO B
VALUES
(5,2,14,'Sanjay')
INSERT INTO B
VALUES
(6,3,15,'Vivek')

INSERT INTO C
VALUES
(10, 'Ashish Data1')
INSERT INTO C
VALUES
(11, 'Ashish Data2')

INSERT INTO C
VALUES
(12, 'Ashish Data3')

INSERT INTO C
VALUES
(13, 'Ashish Data4')

INSERT INTO C
VALUES
(14, 'sanjay Data1')

INSERT INTO C
VALUES
(15, 'Vivek Data1')

Я думал, что следующие удалят все данные из всех таблиц: -

DELETE a FROM A a
INNER JOIN B ON A.AId = B.AId
INNER JOIN C ON B.CId = C.CID

Вместо этого мне пришлось написать это: -

DELETE a FROM A a
INNER JOIN B ON A.AId = B.AId

DELETE b FROM B b
INNER JOIN C ON B.CId = C.CID

Есть ли способ удалить все данные в одном операторе удаления?

Ответы [ 4 ]

1 голос
/ 28 октября 2010

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

Таким образом, в вашем случае таблица B является дочерней.таблица для таблицы A и таблицы C.

Таким образом, у вас не может быть одного оператора delete для удаления данных из всех таблиц.Вместо этого вы можете удалить строку из таблицы A и удалить соответствующие дочерние строки из таблицы B.

Аналогичным образом, удаление из таблицы C удалит соответствующие дочерние строки из таблицы B.

Редактировать - написанные вами запросы удаляются без предложения where.Итак, если вы пытаетесь удалить все строки из таблицы A и таблицы C и там, удалив все ссылочные строки в таблице B, вы можете использовать это -

DELETE FROM A --deletes all rows in A and corresponding referenced rows in B

DELETE FROM C --deletes all rows in C and corresponding referenced rows in B
1 голос
/ 28 октября 2010

В принципе, если я правильно понял, вы можете удалить данные только из «b», и это приведет к удалению данных в «a» и «c».

A <- B [delete] --> C

с веб-сайта Microsoft :

ON DELETE CASCADE

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

0 голосов
/ 28 октября 2010

Вы не можете удалить записи из A и C с помощью одного оператора, поскольку эти таблицы не находятся в транзитивных ссылочных отношениях.

Если вы хотите удалить все записи из A и C, которые имеют соответствующие записи в B, вы должны использовать два оператора:

DELETE  a
FROM    a
JOIN    b
ON      b.aid = a.aid

DELETE  c
FROM    c
JOIN    b
ON      b.cid = c.cid
0 голосов
/ 28 октября 2010

Хм, возможно ли изменить ограничения?

Проблема, как я вижу, состоит в том, что C имеет 1 к многим с A, а B имеет 1 к многим с C, поэтому вместо того, чтобы AId был внешним ключом в B, пусть AId будет внешним ключом в C , Так что, если вы удалите человека из A, он будет каскадно C, который будет каскадом B. Если вы удаляете элемент из C, он будет каскадно перемещаться в B, но не в A, и если вы удаляете элемент из B, это не повлияет ни на одну из двух других таблиц.

Мое предложение:

CREATE TABLE [A] (
    [AId] [int] NOT NULL ,
    [AName] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    CONSTRAINT [PK_A] PRIMARY KEY  CLUSTERED 
    (
        [AId]
    )  ON [PRIMARY] 
) ON [PRIMARY]
GO

CREATE TABLE [C] (
    [CId] [int] NOT NULL ,
    [CName] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    [AId] [int] NULL ,
    CONSTRAINT [PK_C] PRIMARY KEY  CLUSTERED 
    (
        [CId]
    )  ON [PRIMARY] ,
    CONSTRAINT [FK_C_A] FOREIGN KEY 
    (
        [AId]
    ) REFERENCES [A] (
        [AId]
    ) ON DELETE CASCADE 
) ON [PRIMARY]
GO

CREATE TABLE [B] (
    [BId] [int] NOT NULL ,
    [AId] [int] NULL ,
    [CId] [int] NULL ,
    [BName] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
    CONSTRAINT [PK_B] PRIMARY KEY  CLUSTERED 
    (
        [BId]
    )  ON [PRIMARY] ,
    CONSTRAINT [FK_B_C] FOREIGN KEY 
    (
        [CId]
    ) REFERENCES [C] (
        [CId]
    ) ON DELETE CASCADE  NOT FOR REPLICATION 
) ON [PRIMARY]
GO

При такой настройке Delete From A очистит все 3 таблицы за один раз.

Редактировать: вы можете оставить AId в B, чтобы облегчить объединение, но это никак не связано с каскадом удаления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...