SQL löschen Kaskade nicht funktioniert
-
12-10-2019 - |
Frage
Ich habe eine Microsoft SQL-Datenbank mit 2 Tabellen: Hund und Katze
.„dog“ Tabelle hat einen Primärschlüssel Spalte „Lebensmittel“ genannt, die auf eine Spalte „Lebensmittel“ sowie in der „Katze“ Tabelle genannt verwandt ist, die als Fremdschlüssel wirkt.
Die Beziehung zwischen den Tabellen hat einen „auf Lösch Kaskade“ Regelsatz, so dass, wenn ich eine Reihe von „Hund“ Tabelle löschen, die Relveant Zeilen aus „cat“ Tabelle sollten auch gelöscht werden.
Aber die Zeilen in "cat" Tabelle tun net get gelöscht, sie bleiben. Ich verwende den Microsoft SQL-Datenbank-Manager die Zeile in "dog" Tabelle zu löschen.
Jede Idee, warum dies geschieht? brauche ich einen speziellen Lösch SQL-Befehl verwenden, um eine Zeile in dieser Weise zu löschen?
// edit
das Skript für die Tabellen lautet:
USE [VELES]
GO
/****** Object: Table [dbo].[Periods] Script Date: 01/18/2011 14:52:19 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Periods](
[PeriodID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[PeriodName] [nvarchar](50) COLLATE Hebrew_CS_AS NULL,
[PeriodStartDate] [smalldatetime] NOT NULL,
[PeriodEndDate] [smalldatetime] NOT NULL,
CONSTRAINT [PK_Periods] PRIMARY KEY CLUSTERED
(
[PeriodID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
USE [VELES]
GO
/****** Object: Table [dbo].[Exams] Script Date: 01/18/2011 14:55:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Exams](
[ExamID] [int] IDENTITY(1,1) NOT NULL,
[ExamUserID] [char](7) COLLATE Hebrew_CS_AS NOT NULL,
[ExamBase] [tinyint] NOT NULL,
[ExamUserTimesAccessed] [tinyint] NULL,
[ExamMaxTimesToOpen] [tinyint] NOT NULL,
[ExamUserLastTimeOpened] [datetime] NULL,
[ExamUserLastTimeFinished] [datetime] NULL,
[ExamTimeToFinish] [int] NOT NULL,
[ExamPassGrade] [int] NOT NULL,
[ExamPeriod] [int] NOT NULL,
[ExamUserRank] [tinyint] NULL,
CONSTRAINT [PK_Exams] PRIMARY KEY CLUSTERED
(
[ExamID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
USE [VELES]
GO
ALTER TABLE [dbo].[Exams] WITH CHECK ADD CONSTRAINT [FK_Exams_Bases] FOREIGN KEY([ExamBase])
REFERENCES [dbo].[Bases] ([BaseID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Exams] WITH NOCHECK ADD CONSTRAINT [FK_Exams_Periods] FOREIGN KEY([ExamPeriod])
REFERENCES [dbo].[Periods] ([PeriodID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Exams] WITH NOCHECK ADD CONSTRAINT [FK_Exams_Users] FOREIGN KEY([ExamUserID])
REFERENCES [dbo].[Users] ([UserID])
ON UPDATE CASCADE
ON DELETE CASCADE
NOT FOR REPLICATION
GO
ALTER TABLE [dbo].[Exams] CHECK CONSTRAINT [FK_Exams_Users]
GO
ALTER TABLE [dbo].[Exams] WITH CHECK ADD CONSTRAINT [UserRanks_Exams_FK1] FOREIGN KEY([ExamUserRank])
REFERENCES [dbo].[UserRanks] ([RankID])
ON UPDATE CASCADE
ON DELETE CASCADE
Lösung
Ich habe das Problem gelöst.
In der Beziehung Fenstern gibt es eine Option namens Enforce Foreign Key Constraint
, die auf „Nein“ gesetzt wurden.
Ich stelle es auf „Ja“ und jetzt rudern Löschung gut funktioniert.
Andere Tipps
Können Sie zeigen Sie Ihre Tabellenstruktur konkreter? Es klingt wie Sie den PK / FK der falsche Weg, um sich zu haben.
Löschen des FK Teil (Kind) nichts mit dem PK Rekord tun (Stamm). Nur wenn Sie die PK Datensätze löschen tut es um die untergeordneten Datensätze Kaskade, die auf es.
Sind Sie die Spalte food
in dog
sicher, dass der Primärschlüssel dog
? Wenn Sie eine Tabelle mit dem Namen food
haben, dann sollte es die Spalte food
der Primärschlüssel food
sein und ein Fremdschlüssel von dog
(und cat
als auch). Dann mit on delete cascade
Deletionen auf food
die entsprechenden Zeilen auf dog
und cat
verursacht gelöscht werden.
Für Menschen mit SQL Server Management Studio:
Ich habe absolut Fälle gesehen, wo die Benutzeroberfläche mit dem DB synchron aus gelangt ist, auch wenn es Sie die Schlüssel-Liste aktualisiert oder eine völlig neue Instanz geöffnet.
Für meinen Fall habe ich eine Order
die DiscountedItem
geordneten Elemente hat.
Die Art und Weise zu überprüfen, ob die Dinge synchron sind out ist auf der rechten Maustaste auf FK_DiscountedItem_Order
und wählen Sie Script Key as CREATE To Clipboard
und dann untersuchen, was Sie bekommen:
Sie sollte etwas wie diese:
ALTER TABLE [dbo].[DiscountedItem] WITH NOCHECK ADD CONSTRAINT [FK_DiscountedItem_Order] FOREIGN KEY([OrderId])
REFERENCES [dbo].[Order] ([OrderId])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[DiscountedItem] CHECK CONSTRAINT [FK_DiscountedItem_Order]
GO
Wo man deutlich DELETE CASCADE
sehen kann.
Wenn Sie so etwas wie die folgenden bekommen, dann ist die Kaskade Regel ist nicht wirklich aktiv trotz allem, was der UI sagen kann:
ALTER TABLE [dbo].[DiscountedItem] WITH CHECK ADD CONSTRAINT [FK_DiscountedItem_Order] FOREIGN KEY([OrderId])
REFERENCES [dbo].[Order] ([OrderId])
GO
Ich löschte es nur (musste tatsächlich zweimal löschen) und neu erstellt es die richtige SQL zu bekommen.
Sie müssen möglicherweise etwas laufen für ‚verwaiste‘ untergeordnete Zeilen überprüfen:
select * from DiscountedItem where DiscountedItem.orderid not in (select orderid from [order])
Und dann, wenn es sicher ist, dies zu tun:
delete from DiscountedItem where DiscountedItem.orderid not in (select orderid from [order])
Warum ist das passiert?
I nur fügte der Zwang und bekam sofort einen Fremdschlüssel Fehler, weil ich verwaiste Reihen hatte. Etwas dann wurde verwirrt und dachte Kaskade aktiviert wurde.
Also, bevor eine neue Einschränkung in der Benutzeroberfläche mir die Schaffung empfehlen Sie immer zuerst für verwaiste Zeilen zu überprüfen. Sie müssen sie trotzdem löschen, wenn sie vorhanden sind.
Wenn die Katze Tabelle der Schlüssel für den Fremdschlüssel ist, dann eine Reihe von Hund Löscht nicht eine Zeile von Katze zu löschen, vielmehr wäre es um die andere Art und Weise arbeiten.
Diese Nähte gut funktionieren.
delete from Periods where PeriodID = 1
wird eine Reihe von Perioden löschen und alle Zeilen aus Prüfungen, die haben ExamPeriod = 1