SQL delete query with foreign key constraint - sql

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

Related

Two FKs pointing to same parent column - ON UPDATE CASCADE - SQL Server

Here's the scenario.
- Parent Table: TEAMMEMBERS, with a primary key RecID
- Child Table: TEAMMEMBERTASKS
I have two columns in the TEAMMEMBERTASKS table, ReportedBy and AssignedTo.
Both of these columns use the RecID to store which team member reported a task and which team member the task is assigned to. The RecID could be the same for both columns, but that is not always the case.
I need to add in a FK for both child columns that check the relationship to the parent, and I would like to add ON UPDATE CASCADE to both of the foreign keys.
Whenever I try to do this, my second foreign key throws a 'may cause cycles or multiple cascade paths' error.
Here's my code:
ALTER TABLE [dbo].[TEAMMEMBERTASKS] WITH CHECK ADD CONSTRAINT
[FK_AssignedTo_TeamMemberRecID] FOREIGN KEY([AssignedTo])
REFERENCES [dbo].[TEAMMEMBERS] ([RecID])
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] CHECK CONSTRAINT
[FK_AssignedTo_TeamMemberRecID]
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] WITH CHECK ADD CONSTRAINT
[FK_ReportedBy_TeamMemberRecID] FOREIGN KEY([ReportedBy])
REFERENCES [dbo].[TEAMMEMBERS] ([RecID])
ON UPDATE CASCADE
GO
ALTER TABLE [dbo].[TEAMMEMBERTASKS] CHECK CONSTRAINT
[FK_ReportedBy_TeamMemberRecID]
GO
With the current code, will this cause the RecID to be updated in both child columns or will it cause the update command to be restricted?
Should I just go ahead and write up a trigger that deals with this instead?

Create SQL one-to-many relationship with itself

I'm trying to create a one-to-many relationship on a table A with it's own records.
I thought I could just create a second table B, with two foreign keys linking to table A. It appears that this is not sufficient, as LINQ-to-SQL generated a one-to-one relationship. What am I missing?
Some context: table A contains tags, and tags can be sub tags of tags.
Edit: Maybe I need a many-to-many relationship?
Assuming you have a table with the following columns itemid and MasterID
in the column masterid you have the itemid of the item it links to
select a.Itemid,b.itemid from table1 as a inner join table1 as b on a.Itemid=b.MasterID
Above query will give you a result like this :
a_itemid b_itemid
3020079 3020334
3020079 3020335
3045396 3045397
3045396 3045398
3045396 3045401
3020079 3577149
SQL server won't let you create a foreign key for the table referencing itself with ON DELETE CASCADE or ON UPDATE CASCADE since it may cause cycles or multiple cascade paths. But you can create foreign key with ON DELETE NO ACTION and ON UPDATE NO ACTION.
ALTER TABLE tagtablename ADD FOREIGN KEY ([parent_id]) REFERENCES [tagtablename] ([id]) ON DELETE NO ACTION ON UPDATE NO ACTION
You also need to make the two keys in your link table B, the primary key of this table.
Also, Linq2SQL seems to generate properties based on the names of your keys. This resulted in some odd names for me.

Should a foreign key be created on the parent table or child table?

What's the difference? If I have these two tables:
CREATE TABLE Account (Id int NOT NULL)
CREATE TABLE Customer (AccountId int NOT NULL)
And I want a foreign key linking the two, which of the following should I do and why?
Option 1:
ALTER TABLE [dbo].[Customer] WITH CHECK
ADD CONSTRAINT [FK_Accounts_Customers] FOREIGN KEY([AccountId])
REFERENCES [dbo].[Account] ([Id])
Option 2:
ALTER TABLE [dbo].[Account] WITH CHECK
ADD CONSTRAINT [FK_Accounts_Customers] FOREIGN KEY([Id])
REFERENCES [dbo].[Customer] ([Id])
Depends on context. Does every customer have a client? Which one is the parent? It seems like an Account has multiple Customers, in which case the reference belongs on the Customer table.
Now, that said, please call the entities CustomerID and AccountID everywhere. It may seem redundant on the primary table but the name should be consistent throughout the model.
I would use a foreign key from the child to the parent. The tell tale question is: what happens if you need to delete one of the entities?
A FK (foreign key) tells the DBMS that values for subrows for a column list must appear elsewhere as values for subrows for a column list. Whenever that happens (and it isn't already implied by other declartions) declare the FK. If in addtion you want a CASCADE action applied to the referenced table on a change to the referencing table, declare that.
(There's nothing special about CASCADE that it couldn't be offered for non-FK situations. It just comes up frequently with FKs, and there's an explicit graph of FKs by which to reasonably restrict their interactions.)
If there is a FK cycle then you will need to use triggers. Your decision of which constraint(s) are enforced declaratively & which by trigger should consider the graph of (desired) constraints.

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

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.

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.