I am trying to create a new table with "on delete" and "on update" referential triggered actions, but it keeps saying that there is a syntax error. When I tried to run the script, the error message is "missing right parentheses". I don't understand why this is not right.
CREATE TABLE PERSON
(SSN VARCHAR(9) NOT NULL,
Name VARCHAR(20) NOT NULL,
Phone VARCHAR(10),
Address VARCHAR(40),
Employer VARCHAR(20),
Insurer VARCHAR(20),
PCP INT,
CONSTRAINT PERPPK
PRIMARY KEY(SSN),
CONSTRAINT PEREMPFK
FOREIGN KEY(Employer) REFERENCES EMPLOYER(Name)
ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT PERINSFK
FOREIGN KEY(Insurer) REFERENCES INSURER(Name)
ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT PERPCP
FOREIGN KEY(PCP) REFERENCES PHYSICIAN(PID)
ON DELETE SET NULL ON UPDATE CASCADE);
ON UPDATE CASCADE is not valid syntax. There is no direct way to do this and for good reason. You should not be creating a model where you have to update values in Primary keys. Primary keys should only be created and dropped, never updated. If it is being updated, then it is probably not a primary key. But that is a design consideration that you would have to make.
If you want to implement something like cascading updates, you could maybe do it with a stored procedure and deferrable constraints. Defer the constraint and update both the parent and foreign keys before committing.
Here is the asktom discussion on this. Another.
Related
I have a database design like below. I have 3 tables Compartment, CompartmentRelation and CompartmentRelationType . CompartmentRelation table keeps the other compartments around the selected compartment (below,above,behind,infront,etc). CompartmentRelationType keeps the position. Think that i have compartments in the Compartment table named comp-1, comp-2, comp-3, comp-4 and insert the the compartments above comp-1 as comp-2,comp-3 in CompartmentRelation as below. Problem is that setting delete action as cascade for the column RelatedCompId in CompartmentRelation table throw the excaption as
Unable to create relationship 'FK_CompartmentRelation_Compartment1'.
Introducing FOREIGN KEY constraint 'FK_CompartmentRelation_Compartment1' on table 'CompartmentRelation' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
Which way should i follow ?
Compartment
comp-1
comp-2
comp-3
comp-4
Compartment Relation
comp-1 -> comp-2
comp-1 -> comp-3
CREATE TABLE [dbo].[Compartment] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (500) NOT NULL,
CONSTRAINT [PK_Compartment] PRIMARY KEY CLUSTERED ([Id] ASC),
CREATE TABLE [dbo].[CompartmentRelation] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[CompId] INT NOT NULL,
[RelationTypeId] INT NOT NULL,
[RelatedCompId] INT NOT NULL,
CONSTRAINT [PK_CompartmentRelation] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_CompartmentRelation_CompartmentRelationType] FOREIGN KEY ([RelationTypeId]) REFERENCES [dbo].[CompartmentRelationType] ([Id]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [FK_CompartmentRelation_Compartment1] FOREIGN KEY ([RelatedCompId]) REFERENCES [dbo].[Compartment] ([Id]),
CONSTRAINT [FK_CompartmentRelation_Compartment] FOREIGN KEY ([CompId]) REFERENCES [dbo].[Compartment] ([Id]) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE TABLE [dbo].[CompartmentRelationType] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (200) NOT NULL,
[NameLan1] NVARCHAR (200) NOT NULL,
[NameLan2] NVARCHAR (200) NULL,
CONSTRAINT [PK_CompartmentRelationType] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Problem is that setting delete action as cascade for the column
RelatedCompId in CompartmentRelation table throw the excaption as
Unable to create relationship
'FK_CompartmentRelation_Compartment1'. Introducing FOREIGN KEY
constraint 'FK_CompartmentRelation_Compartment1' on table
'CompartmentRelation' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other
FOREIGN KEY constraints. Could not create constraint or index.
See previous errors.
The basic issue appears to be that deletes from table Compartment (and updates to its PKs) can cascade to CompartmentRelation through two different foreign keys. If you intend to support Compartments being related to themselves, then that's end-of-story for cascading from Compartment to CompartmentRelation -- you can't do it.* If you intend to forbid self relationships then you could try adding a check constraint to CompartmentRelation to enforce that prohibition, though I'm not at all sure that SQL Server will take that into account.
If SQL Server won't accept the cascading deletes then you have at least three options:
Make it an application responsibility to clean up compartment relationships before deleting compartments. (And don't cascade.)
Create triggers to handle relationship deletion when compartments are deleted. (And don't cascade.)
Create a stored procedure for deleting compartments, and make it handle the needed relationship deletions. (And don't cascade.)
Which way should i follow ?
Whichever of those makes the most sense for your application. All have advantages and disadvantages.
Additionally,
Do not cascade updates of surrogate key columns, especially when the key values are machine generated, as all yours are. Those keys should never be updated in the first place, and if an attempt were ever made to update one then it would be better for the DB to reject it, for whatever reason, than to accept it.
You probably don't want to cascade deletions of CompartmentRelationType to ComponentRelation. Including such cascading allows for deleting all the relations of a given type by deleting the type itself, but such a cascade is more likely to be performed mistakenly than intentionally, and if it were performed mistakenly then the resulting data loss would be significant. It's probably better to make the application delete all those relations explicitly if that's what it really means to do, and otherwise to reject deletion of types that are in use by existing relations.
*Technically, you could do it by cascading from only one of the two FKs with Compartment, but it seems unlikely that such a half-measure would serve your purposes.
Have tried looking through the code up-and-down and cannot get it to work. Was mostly trying out the Create table function. Worked fine until trying to create a table with composite primary key. Absolutely stumped. Any help is appreciated.
Tried removing the names for the keys, but then was redirected to a different sort of error: "invalid datatype"
Create Table Cust_Artist_EOI (ArtistID Number(38) Not Null,
CustomerID Number(38) Not Null,
Constraint Cust_Artist_EOI_PK Primary Key(ArtistID, CustomerID),
Constraint Cust_Artist_EOI_ArtistFK Foreign Key(ArtistID)
References MyArtist(ArtistID)
On Update No Action
On Delete Cascade,
Constraint Cust_Artist_EOI_CustFK Foreign Key(CustomerID)
References MyCustomer(CustomerID)
On Update No Action
On Delete Cascade);
The problem is the on update. Remove that:
Create Table Cust_Artist_EOI (
ArtistID Number(38) Not Null,
CustomerID Number(38) Not Null,
Constraint Cust_Artist_EOI_PK Primary Key(ArtistID, CustomerID),
Constraint Cust_Artist_EOI_ArtistFK Foreign Key(ArtistID)
References MyArtist(ArtistID) On Delete Cascade,
Constraint Cust_Artist_EOI_CustFK Foreign Key(CustomerID)
References MyCustomer(CustomerID) On Delete Cascade
);
Here is a db<>fiddle.
If you look in the syntax diagram for foreign key constraint in Oracle, you will see that neither on update nor no action is supported.
I'm not sure why no action is not supported, because that is the default behavior (and I think it is a good idea to be able to express default behavior).
Not supporting on update is a better idea. It discourages changes to primary keys. And changing primary keys is generally a bad idea.
I have a task:
If a "shop" is deleted all references to it is set to NULL.
When I try to create a table:
CREATE TABLE TEST
(
id int Primary Key,
shop int FOREIGN KEY REFERENCES TEST(id) ON DELETE SET NULL,
);
I get an error:
Introducing FOREIGN KEY constraint 'FK__TEST__shop__2882FE7D' on table 'TEST' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 0, Line 1
What am I doing wrong?
You are getting an error because you are creating a table with a reference to itself. This is not a good idea, and also this is not what you want.
For your task, you need to create another table, with a relationship (a foreign key) that references your first table. The foreign key must be defined properly to hold the rule that sets the child to NULL when the parent is deleted, like :
CONSTRAINT fk_name
FOREIGN KEY (child_col)
REFERENCES parent_table (parent_col)
ON DELETE SET NULL
See this link on how to set option ON DELETE in a foreign key
You can do this, but not exactly as you wish. The following works:
CREATE TABLE TEST (
id int Primary Key,
shop int,
FOREIGN KEY (shop) REFERENCES TEST(id) ON DELETE NO ACTION,
);
To be honest, I'm not sure why the in-line definition doesn't work. The more important point is the action. The SET NULL is not allowed, because SQL Server is very cautious about potential cycles. However, NO ACTION is allowed.
I have the following DDL that I am using with SQL Server 2012:
CREATE TABLE Subject (
[SubjectId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (50) Not NULL,
CONSTRAINT [PK_Subject] PRIMARY KEY CLUSTERED ([SubjectId] ASC)
)
CREATE TABLE Topic (
[TopicId] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[SubjectId] INT NOT NULL,
CONSTRAINT [PK_Topic] PRIMARY KEY CLUSTERED ([TopicId] ASC)
)
ALTER TABLE [Topic] WITH CHECK ADD CONSTRAINT [FK_TopicSubject]
FOREIGN KEY([SubjectId]) REFERENCES [Subject] ([SubjectId])
ON DELETE CASCADE
CREATE TABLE SubTopic (
[SubTopicId] INT IDENTITY (1, 1) NOT NULL,
[TopicId] INT NOT NULL,
[Name] NVARCHAR (4000) Not NULL,
CONSTRAINT [PK_SubTopic] PRIMARY KEY CLUSTERED ([SubTopicId] ASC)
)
ALTER TABLE [SubTopic] WITH CHECK ADD CONSTRAINT [FK_SubTopicTopic]
FOREIGN KEY([TopicId]) REFERENCES [Topic] ([TopicId])
ON DELETE CASCADE
When I try to run the scripts I get the following message:
{"Introducing FOREIGN KEY constraint 'FK_TopicSubject'
on table 'Topic' may cause cycles or multiple cascade paths.
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION,
or modify other FOREIGN KEY constraints.\r\nCould not create constraint.
See previous errors."}
What I really need is for when a person tries to DELETE a subject when there are topics for the delete to fail. If I include neither DELETE ON CASCADE or DELETE NO ACTION then will this happen. If not then how can I stop the delete on subject happening if there are Topics for that subject?
Short answer is: If you don’t want cascade updates and deletions then use ON DELETE NO ACTION. Same applies for Update.
Here is a copy from MSDN article (it’s SQL Server 2000 but same rules still apply)
ON DELETE NO ACTION
Specifies that if an attempt is made to delete a row with a key referenced by foreign keys in existing rows in other tables, an error is raised and the DELETE is rolled back.
ON UPDATE NO ACTION
Specifies that if an attempt is made to update a key value in a row whose key is referenced by foreign keys in existing rows in other tables, an error is raised and the UPDATE is rolled back.
Please refer to this link. It has given a detail explanation of this error, and also has suggested to create a trigger as an alternative.
Foreign key constraint may cause cycles or multiple cascade paths?
I had a weird problem when I am trying to create tables in MySQL.
I want to have a cross reference two many-to-many tables and here is the code I create table
create table teacher(
t_id char(10) not null unique,
name varchar(20) not null,
sur_name varchar(20) not null,
CONSTRAINT pk_teacher PRIMARY KEY(t_id))
create table student(
s_id char(10) not null unique,
name varchar(20) not null,
sur_name varchar(20) not null,
CONSTRAINT pk_student PRIMARY KEY(s_id))
create table teacher_student(
t_id char(10) not null,
s_id char(10) not null,
CONSTRAINT pk_teacher_student PRIMARY KEY(t_id, s_id))
in order to add foreign constraints I used the following code
ALTER TABLE teacher_student
ADD CONSTRAINT fk_teacher_student FOREIGN KEY(s_id) REFERENCES student(s_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_student_teacher FOREIGN KEY(t_id) REFERENCES teacher(t_id)
ALTER TABLE student
ADD CONSTRAINT fk_student_teacher_student
FOREIGN KEY(s_id) REFERENCES teacher_student(s_id)
ALTER TABLE teacher
ADD CONSTRAINT fk_teacher_teacher_student
FOREIGN KEY(t_id) REFERENCES teacher_student(t_id)
that works fine but if I try to execute code in a different order like this
ALTER TABLE student
ADD CONSTRAINT fk_student_teacher_student
FOREIGN KEY(s_id) REFERENCES teacher_student(s_id)
ALTER TABLE teacher
ADD CONSTRAINT fk_teacher_teacher_student
FOREIGN KEY(t_id) REFERENCES teacher_student(t_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_teacher_student FOREIGN KEY(s_id) REFERENCES student(s_id)
ALTER TABLE teacher_student
ADD CONSTRAINT fk_student_teacher FOREIGN KEY(t_id) REFERENCES teacher(t_id)
ALTER TABLE student
I am getting exception
Can't create table 'test.#sql-44c_37' (errno: 150)
My question is, why the order is important? what is the difference between these two ways of creating constraints? thanks
"I try to execute code in a different order like this" You have no different order you have extremely different constraints. You can't create such constraints.
Examine this article for more information
FOREIGN KEY Constraints
Some of your foreign keys don't seem to make any sense.
Those referencing student and teacher (the fk_teacher_student and fk_student_teacher ones) are fine. That's actually a typical case of a many-to-many table referencing each of the two entity tables whose many-to-many relationship is being implemented.
Now, what are you proposing with referencing back from those tables to the many-to-many one? I admit that I can't really explain why the foreign keys were successfully added using the first script and failed with the other. Sorry about that. Even though I've got some vague idea, that's not really the point of my answer. The point is, your present design is going to make it difficult for you to add new data. With it, you can't really add, say, a student without adding also a relationship between the new student and an existing teacher. This is because a row in student is supposed to reference an existing student in teacher_student, but since it is a new student, there's no corresponding row in teacher_student yet. Same goes for a new teacher.
So, consider just abandoning the idea of fk_student_teacher_student and fk_teacher_teacher_student. They are not needed to your design. They have already caused you to solve an unnecessary problem and they are likely to cause more trouble in the future.