foreign key data deletion should display error for primary key - sql-server

i have two tables Table1 and Table2. Where table1 column primary key is referred to table2 column as foreign key.
Now i have to display a error message of constraint violation when ever i delete records from table2 which is having foreign key column of table1.

If I get it right your column A (say) in table 1 references column B (say) in table 2.
What you can do is set the ON DELETE to NO ACTION which will prevent deletion of records from table 2 if any children of it still exists in table 1.
You can can do this by:
ALTER TABLE TABLE1 ADD FOREIGN KEY (A) REFERENCES TABLE2 (B) ON DELETE NO ACTION;

You don't have a constraint violation if you delete records from the child table and not the parent. It is normal to delete child records. For instance if I have a user table and a photos tables that contains the userid from the users table, why would I want to stop that action and throw an error if I want to delete a photo? Deleting a child record doesn't also delete the parent.
If you really want to do that, then you must do it through a trigger (make sure to handle multiple record deletes) or if the FK is a required field, then simply don't grant permissions to delete to the table. Be aware that this may mean you can never delete any records even when you try to delete. A simple method may be to not have a delete function available in the application.
I suspect what you really need to a to get a better definition of what is needed in the requirements document. In over 30 years of dealing with hundreds of databases, I have never seen anyone need this functionality.

Related

using a trigger to delete all referenced all IDs referenced to an ID

pls guys...is there a way delete all iDs referenced to particular ID in a database when that particular ID is deleted?
take for instance i have a company data that has list of departments with staff under them and also all those staff have different records under them like attendance, bio data, salary scheme e.t.c.
the way i designed my database is that staffs under a department are referenced to that department using a foreign key and like wise all records under a particular staff is referenced to that staff using a foreign key.
now, is it possible to have a sort of trigger or any other sort of mechanism so that when i delete a staff from the staffs table every other record referenced to that staff will be deleted also.
i would have considered using multi table delete but since am using java sqlite, it doesnt support that from what i read. And i wouldnt like to go through the stress of having to delete all records one after the other from all the tables.
thanks a lot guys
ON DELETE CASCADE could help you. Take a look at the documentation:
CASCADE: A "CASCADE" action propagates the delete or update operation on the parent key to each dependent child key. For an "ON DELETE CASCADE" action, this means that each row in the child table that was associated with the deleted parent row is also deleted.
you just need to reference the row id of the parent table:
CREATE TABLE parentTable(
parent_id INTEGER PRIMARY KEY,
data TEXT
);
CREATE TABLE childTable(
child_id INTEGER,
parent_id INTEGER REFERENCES parentTable(parent_id) ON DELETE CASCADE
);
and I think you would also need to active the foreign keys for this to work:
PRAGMA foreign_keys = ON;

How to delete record in Parent table without affecting the Child table?

I have 2 tables in my database, Table A and Table B.
Table A is a Master table and table B is a Transaction table. Table B have Foreign Key (IdTableA)
Example :
I already have a record in table B with IdTableA in it.
INSERT INTO Table_B VALUES (IdTableB, IdTableA, 500000);
and when I tried to delete record in Table A which is IdTableA there is an error.
I want to delete a record in Table A without affecting record in Table B
what should i do ? is it possible ?
You didn't post the error message, but most likely the IdTableA column is a foreign key to Table A. That means a row in Table A can't be deleted if any row in Table B references that row. There is no way to get around this except to permanently remove the foreign key.
The purpose of a foreign key is to prevent exactly this scenario. It prevents data integrity problems where rows would otherwise make no logical sense because other rows they reference do not actually exist.
http://en.wikipedia.org/wiki/Foreign_key

Deleting related records in another table with "Where"-like considerations

I have a data table with a primary key called OptDefID. When a record in this table is deleted I need to go and delete all records from the Permissions table that have that OptDefID in the defID field (in Permissions). The tricky part for me is that the Permissions table does not have a primary key and holds lots of different kinds of permissions, and has a permissiontype field. I need to delete rows that have the OptDefID AND a permissiontype of OptDef.
Because I need to consider the permissiontype, I don't believe a Foreign Key Constraint is appropriate here (or is it?).
I've also considered creating a trigger, but am unsure how to get the OptDefID passed into the trigger.
I can do this via the application itself, but I feel like this should be a database level solution.
What's the best solution?
Say I want to delete from Permissions where defID is 20 and permissiontype is 'OptDef'. There may be another row in Permissions that has a defID of 20, but has a permissiontype of 'Member'. That show should not be deleted because it pertains to Members and not Opt data.
Storing table names in fields prevents foreign keys from working properly, as you have discovered.
I recommend you fix the root problem and separate these two foreign keys, so each of them can be individually enforced. For example:
CREATE TABLE Permissions (
...
OptDefId int,
MemberId int,
FOREIGN KEY (OptDefId) REFERENCES OptDef ON DELETE CASCADE,
FOREIGN KEY (MemberId) REFERENCES Members ON DELETE CASCADE,
CHECK (
(OptDefId IS NOT NULL AND MemberId IS NULL)
OR (OptDefId IS NULL AND MemberId IS NOT NULL)
)
)
The CHECK makes sure only one of the FKs is non-NULL and only non-NULL FKs are enforced.
Alternatively, you could avoid changing your current design and enforce this "special" FK through a trigger, but declarative constraints should be preferred to triggers when possible - declarative constraints tend to leave less room for error and be more "self-documenting".
In case the OptDefId column is only filled when the record in question references the Permissions table, a foreign key should be appropriate. I.e. you have another column MemberId, which in turn could be a foreign key on a Members table.
It is only when you have a single column - let's call it ObjectId - which takes on other meanings as the contents of the type column change, that you cannot use foreign keys.
In that case, a trigger would probably be the best approach, as you already guessed. I only know about triggers in Oracle PL/SQL, where they are passed in as separate, complete rows representing the old and new state. I guess it will be analogous in MS-SQL-Server.
In addition to using join with SELECT statements, you can also join multiple tables in DELETE & UPDATE statements as well.
As I understand the issue, you should be able to join the Permissions table to the table with the OptDefID column & add a WHERE clause similar to the this:
DELETE MyTable
...
WHERE [Permissions].permissiontype = 'OptDef'
Also, these links may be of interest too:
SQL DELETE with JOIN another table for WHERE condition (for MySQL, but still relevant)
Using A SQL JOIN In A SQL DELETE Statement
Using A SQL JOIN In A SQL UPDATE Statement

SQL Server - Maintain Referential Integrity without CASCADE and INSTEAD OF trigger

I have a table (TableB) that has a foreign key relationship with a parent table (TableA).
When I delete a record in Table A, I want to preserve referential integrity by deleting all records in TableB that reference the deleted record in TableA.
Normally I would ON DELETE CASCADE. However due to the table structure and the overprotective safeguards against multiple cascade paths in SQL Server, this is not possible for this specific relationship.
I also cannot use an INSTEAD OF trigger as TableA itself has a CASCADE foreign key relationship on it.
What I'm thinking of doing is changing the relationship between TableA and TableB to ON DELETE SET NULL, then creating an AFTER trigger to cleanup the NULL records in TableB.
Are there better ways of dealing with this scenario?
Can you change the other constraint that is preventing you from adding this one as ON DELETE CASCADE?
Can you add a DeleteMe column, then issue an UPDATE A SET DeleteMe = 1, then use an after trigger to delete Table B rows first, then the requested table A rows?
Can you split or merge tables (vertically, that is) in some way that separates their mutually exclusive dependencies?

SQL Server 2008 - Multiple Cascading FK's - Do i need a trigger?

I have a 1..* relationship between User and Post. (one user has many posts)
Post has a FK called "UserId", which maps to the "UserId" field on User table.
I tried to set this FK as Cascade UPDATE/DELETE, but i get this error:
'Users' table saved successfully
'Posts' table
- Unable to create relationship 'FK_Posts_Users'.
Introducing FOREIGN KEY constraint 'FK_Posts_Users' on table 'Posts' 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.
I have a table called PostHelpful. One Post has many Helpful's.
Helpful has a cascading FK to User (so when a User is deleted, their Helpful's are also deleted).
But i think this is the cause of complaint for "multiple cascade paths".
Because if i delete a User (currently), it will delete their helpfuls. But im trying to add a cacade to Post also, do it would delete the Post, then try and delete the Helpful's for that Post (as Helpful also has a cascading FK to Post). In that scenario, which cascading FK would SQL choose?
Here is the database diagram of the three tables in question:
As you can see, "PostHelpful" is a child to both "Post" and "User" (has FK's to both).
So i can't make both keys cascading? Do i need a trigger on "Users" (AFTER DELETE) to manually delete the helpfuls (and other tables referencing User).
It's not a matter of which path will SQL Server choose, it does not allow it so that it won't wind up in a compromising position. When we ran into this situation, we had to resort to a trigger.
1) As the error message stated, change the Users_PostHelpfuls FK to ON DELETE NO ACTION.
2) Add an INSTEAD OF DELETE trigger to Users:
CREATE TRIGGER dbo.Users_IO_Delete
ON dbo.Users
INSTEAD OF DELETE
AS
BEGIN;
DELETE FROM dbo.PostHelpfuls WHERE UserId IN (SELECT UserId FROM deleted);
DELETE FROM dbo.Users WHERE UserId IN (SELECT UserId FROM deleted);
END;
Now, the FK will still enforce DRI, but the trigger is cascading the delete rather than the FK constraint.
You could replace PostHelpfuls with Posts in the above steps. But when doing this it's best to use the trigger to remove the less independent entity's records. In other words, it's more likely that Posts are related to tables beside Users and PostHelpfuls than PostHelpfuls is related to tables beside Users and Posts.

Resources