How to update 2 columns in 2 tables that have foreign key - sql

I know the question of how to update multiple tables in SQL has been asked before and the common answer seems to be do them separately in a transaction.
However, the 2 columns I need to update have a foreign key so cannot be updated separately.
e.g.
Table1.a is a foreign key to Table2.a
One of the entries in the tables is wrong, e.g. both columns are 'xxx' and should be 'yyy'
How do I update Table1.a and Table2.a to be 'yyy'?
I know I could temp remove the key and replace but surely there's another way.
Thanks

You can't do the update simultaneously, however you can force SQL to do the update. You need to make sure your foreign keys have the referential triggered action ON UPDATE CASCADE
e.g.
ALTER TABLE YourTable
ADD CONSTRAINT FK_YourForeignKey
FOREIGN KEY (YourForeignKeyColumn)
REFERENCES YourPrimaryTable (YourPrimaryKeyColumn) ON UPDATE CASCADE

Not being a fan of on update cascade, I would suggest a different route.
First you do not update the Parent table, you add a new record with the value you want (and the same data as the other record for all other fields). Then you have no difficulty updating the child tables to use this value instead of that value. Further you now have the ability to to do the work in batches to avoid locking the system up while the change promulgates through it. Once all the child tables have been updated, you can delete the original bad record.

my answer is based on the following link: http://msdn.microsoft.com/en-us/library/ms174123%28v=SQL.90%29.aspx
You need to make sure that your table_constraint will be defined as ON UPDATE CASCADE
CREATE TABLE works_on1
(emp_no INTEGER NOT NULL,
project_no CHAR(4) NOT NULL,
job CHAR (15) NULL,
enter_date DATETIME NULL,
CONSTRAINT prim_works1 PRIMARY KEY(emp_no, project_no),
CONSTRAINT foreign1_works1 FOREIGN KEY(emp_no) REFERENCES employee(emp_no) ON DELETE CASCADE,
CONSTRAINT foreign2_works1 FOREIGN KEY(project_no) REFERENCES project(project_no) ON UPDATE CASCADE)
and then when you will change the value of your primary key
see the following quote:
For ON DELETE or ON UPDATE, if the CASCADE option is specified, the
row is updated in the referencing table if the corresponding
referenced row is updated in the parent table. If NO ACTION is
specified, SQL Server Compact Edition returns an error, and the update
action on the referenced row in the parent table is rolled back.
For example, you might have two tables, A and B, in a database. Table
A has a referential relationship with table B: the A.ItemID foreign
key references the B.ItemID primary key.
If an UPDATE statement is executed on a row in table B and an ON
UPDATE CASCADE action is specified for A.ItemID, SQL Server Compact
Edition checks for one or more dependent rows in table A. If any
exist, the dependent rows in table A are updated, as is the row
referenced in table B.
Alternatively, if NO ACTION is specified, SQL Server Compact Edition
returns an error and rolls back the update action on the referenced
row in table B when there is at least one row in table A that
references it.

Related

How to delete records from parent table which is referenced by multiple child tables?

I have a table which is referenced by multiple tables (around 52) and further,few of the child tables have multiple foreign keys also that is referencing other tables too.
I want to delete a record from parent table, I am unable to do so, as I am getting error "The DELETE statement conflicted with the REFERENCE constraint "FK_xxx". The conflict occurred in database "MyDB", table "dbo.A", column 'x'."
I want a generalized T-SQL solution which is irrespective of tables and number of references.
You have to look at the "on delete" keyword which is a part of the foreign key constraint definition.
Basically you have 4 options:
NO ACTION (does nothing)
CASCADE (deletes the child aswell)
SET NULL (sets the reference field to null)
SET DEFAULT (sets the reference field to the default value)
An example would be:
CREATE TABLE parent (
id INT NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE child (
id INT,
parent_id INT,
INDEX par_ind (parent_id),
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE -- replace CASCADE with your choice
) ENGINE=INNODB;
(for this example and more details look here: http://dev.mysql.com/doc/refman/5.7/en/create-table-foreign-keys.html )
If you now want to modify your constraint, you first have to drop it, and create a new one like for example:
ALTER TABLE child
ADD CONSTRAINT fk_name
FOREIGN KEY (parent_id)
REFERENCES parent(id)
ON DELETE CASCADE; -- replace CASCADE with your choice
I hope this helped. Also to mention it, you should think about maybe not really deleting your parent, and instead creating another boolean column "deleted", which you fill with "yes" if someone clicks the delete. In the "Select"-query you filter then by that "deleted" column.
The advantage is, that you do not lose the history of this entry.
Your problem is this: A FK constraint is designed to prevent you from creating an orphaned child record in any of the 52 tables. I can provide you with the script you seek, but you must realise first that when you try to re-enable the FK constraints the constraints will fail to re-enable because of the orphaned data (which the FK constraints are designed to prevent). For your next step, will have to delete the orphaned data in each of the 52 tables first anyway. It is actually much easier just to redo the constraints with ON DELETE CASCADE, or drop the constraints and forget about referential integrity altogether. You can't have it both ways.

multiple cascade paths, on update cascade

I have a problem with sql server, when I want to have 3 table and make relationship between them, and change the "On Update" property to "cascade".
this problem happend when I want to save the diagram:
Introducing FOREIGN KEY constraint 'FK_Company_Slave' on table 'Company' 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. See previous errors.
in this picture, I define my data base, FK and ....
thanks.
First:
A FOREIGN KEY in one table points to a PRIMARY KEY in another table. if you don't want to use PRIMARY KEY on other table in order to foreign key, you must be create unique index on the table.
Second:
you can create after trigger on Master table in order to develop on update cascade manually. In other word your foreign key between Company table and Master table created without on update cascade and then create following trigger on master to update company table after changed row in Master table.
create trigger triggername on dbo.[Master]
After Insert
AS Begin
Update Company
Set MasterKey = I.MasterKey
From Inserted I
Inner join Deleted D on D.Code = I.Code
Where Company.MasterKey = D.MasterKey
End

SQL delete query with foreign key constraint

I know that this question belongs to the very early stages of the database theory, but I have not encountered such a problem since several months. If someone has a database with some tables associated together as "chain" with foreign keys and they want to delete a record from a table which has some "dependent" tables, what obstacles arise? In particular, in a database with tables: Person, Profile, Preference, Filter exist the associations as Person.id is foreign key in Profile and Profile.id is foreign key in Preference and Filter.id is foreign key in Preference, so as that all the associationsenter code here are OneToMany. Is it possible to delete a Person with a simple query:
Delete from Person p where p.id= 34;
If no, how should look like the query in order to perform the delete successfully?
If the database in the application is managed by hibernate, what constraints (annotations) should I apply to the associated fields of each entity, so as to be able with the above simple query to perform the delete?
FOR SQL VERSION
Look at the Screenshot. you can use the Insert Update Specificaiton Rules. as it has Delete and Update Rules. you can set either of these values.
Foreign key constraints may be created by referencing a primary or unique key. Foreign key constraints ensure the relational integrity of data in associated tables. A foreign key value may be NULL and indicates a particular record has no parent record. But if a value exists, then it is bound to have an associated value in a parent table. When applying update or delete operations on parent tables there may be different requirements about the effect on associated values in child tables. There are four available options in SQL Server 2005 and 2008 as follows:
No Action
Cascade
SET NULL
SET Default
Use this article for Refrence.
http://www.mssqltips.com/sqlservertip/2365/sql-server-foreign-key-update-and-delete-rules/
ORACLE VERSION
you can use one of below.
alter table sample1
add foreign key (col1)
references
sample (col2)
on delete no action;
alter table sample1
add foreign key (col1)
references
sample (col2)
on delete restrict;
alter table sample1
add foreign key (col1)
references sample (col2)
on delete cascade;
for refrance.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm
answer is no if there is foreign key constraint then you have to delete leaf node table data first
that is first delete from Preference table
then from Profile and Filter Table
then delete record from Person table
This is the generic concept that you apply anywhere

ON UPDATE CASCADE with two columns in a single table in SQL Server [duplicate]

I have a database table called Lesson:
columns: [LessonID, LessonNumber, Description] ...plus some other columns
I have another table called Lesson_ScoreBasedSelection:
columns: [LessonID,NextLessonID_1,NextLessonID_2,NextLessonID_3]
When a lesson is completed, its LessonID is looked up in the Lesson_ScoreBasedSelection table to get the three possible next lessons, each of which are associated with a particular range of scores. If the score was 0-33, the LessonID stored in NextLessonID_1 would be used. If the score was 34-66, the LessonID stored in NextLessonID_2 would be used, and so on.
I want to constrain all the columns in the Lesson_ScoreBasedSelection table with foreign keys referencing the LessonID column in the lesson table, since every value in the Lesson_ScoreBasedSelection table must have an entry in the LessonID column of the Lesson table. I also want cascade updates turned on, so that if a LessonID changes in the Lesson table, all references to it in the Lesson_ScoreBasedSelection table get updated.
This particular cascade update seems like a very straightforward, one-way update, but when I try to apply a foreign key constraint to each field in the Lesson_ScoreBasedSelection table referencing the LessonID field in the Lesson table, I get the error:
Introducing FOREIGN KEY constraint 'c_name' on table 'Lesson_ScoreBasedSelection' may cause cycles or multiple cascade paths.
Can anyone explain why I'm getting this error or how I can achieve the constraints and cascading updating I described?
You can't have more than one cascading RI link to a single table in any given linked table. Microsoft explains this:
You receive this error message because
in SQL Server, a table cannot appear
more than one time in a list of all
the cascading referential actions that
are started by either a DELETE or an
UPDATE statement. For example, the
tree of cascading referential actions
must only have one path to a
particular table on the cascading
referential actions tree.
Given the SQL Server constraint on this, why don't you solve this problem by creating a table with SelectionID (PK), LessonID, Next_LessonID, QualifyingScore as the columns. Use a constraint to ensure LessonID and QualifyingScore are unique.
In the QualifyingScore column, I'd use a tinyint, and make it 0, 1, or 2. That, or you could do a QualifyingMinScore and QualifyingMaxScore column so you could say,
SELECT * FROM NextLesson
WHERE LessonID = #MyLesson
AND QualifyingMinScore <= #MyScore
AND #MyScore <= QualifyingMaxScore
Cheers,
Eric

Data Modeling: What is a good relational design when a table has several foreign key constrainst to a single table?

I have 2 tables:
1. Employees
2. Vouchers
Employees table has a single primary key.
Vouchers table has 3 foreign key constraints referencing the Employees table.
The following is a sample T-SQL script (not the actual table script) to create both tables and their relationship in SQL Server:
IF OBJECT_ID('dbo.Vouchers') IS NOT NULL
DROP TABLE dbo.Vouchers
IF OBJECT_ID('dbo.Employees') IS NOT NULL
DROP TABLE dbo.Employees
GO
CREATE TABLE Employees
(
ObjectID INT NOT NULL PRIMARY KEY IDENTITY
)
CREATE TABLE Vouchers
(
ObjectID INT NOT NULL PRIMARY KEY IDENTITY,
IssuedBy INT,
ReceivedBy INT,
ApprovedBy INT,
CONSTRAINT fk_Vouchers_Employees_IssuedBy FOREIGN KEY (IssuedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT fk_Vouchers_Employees_ReceivedBy FOREIGN KEY (ReceivedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION,
CONSTRAINT fk_Vouchers_Employees_ApprovedBy FOREIGN KEY (ApprovedBy)
REFERENCES Employees (ObjectID)
ON UPDATE CASCADE
ON DELETE NO ACTION
)
But an error is thrown:
Msg 1785, Level 16, State 0, Line 7
Introducing FOREIGN KEY constraint 'fk_Vouchers_Employees_ReceivedBy' on table 'Vouchers' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
I don't have an idea of what efficient solution is available here. The requirements on the relationship is that: whenever an Employee is deleted, the Voucher that references some of its columns to the Employee does not get deleted (ON DELETE CASCADE is not an option). Instead, the values of the columns (IssuedBy, ReceivedBy and/or ApprovedBy) that are referenced to the deleted Employee should be set to NULL (since the columns are NULLABLE).
Many thanks!
Strictly from a relational design point of view, the Vouchers table as three Foreign Keys. Whether you choose to enforce them, through CASCADE assertions or otherwise, is an implementation issue, but the relational design still exists. Presumably you want to enforce that, if one of the three fields is not NULL, then a matching record needs to exist. Or not. It's an implementation issue as to whether or not you care to enforce the design.
However, the violations you describe are assumed at your peril. The fact that you're asking this question suggests you may not fully appreciate all the ways these choices can lead into the swamp.
I think the error may be a consequence of the fact that more than one of the three might refer to the same employee.
BTW, I've in very few cases ever found it necessary to delete records in such a fashion that CASCADES are useful. Usually that would be used to prevent the database from being too big; and database capacity is less and less an issue over time.
I would not actually delete Employees, but instead use a trigger to set a flag to mark them as deleted.
I generally don't turn on cascade of Updates or Deletes, but instead require an application to explicitly perform these actions.
From a design standpoint it seems good to have the 3 foreign keys you listed. It looks like the error message you are getting relates to the ON UPDATE CASCADE options on your foreign keys (although I was able to create the table as specified). Regardless, to get the behavior you mention wanting, I would recommend a trigger on the Employees table, that fires before you delete the record. This trigger would find instances of the Employees.OjbectID in the Vouchers table and set them to NULL.