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

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

Related

Can a trigger on a table with a primary key ever be fired with the same primary key appearing twice in either the inserted or deleted table?

If I have a table, T, with a primary key, ID,
CREATE TABLE T (
ID INT NOT NULL PRIMARY KEY,
Data BIT NOT NULL DEFAULT (0)
)
and create an after insert trigger on it
CREATE TRIGGER T_Trigger ON T
FOR INSERT, UPDATE, DELETE
AS
BEGIN
-- Trigger body
END
is it ever possible that the INSERTED table will have duplicate values for the ID column? Or for the DELETED table to have duplicate values for the ID column?
Clearly it's possible for the ID to appear once in each of the INSERTED and DELETED tables.
I can't imagine a DML statement that could lead to a trigger firing with the same primary key occurring twice in either the INSERTED or DELETED table. Even MERGE is carefully documented to say that "The MERGE statement cannot update the same row more than once, or update and delete the same row." The PRIMARY KEY constraint on ID and the limited power of each DML statement seem like they should combine to keep it unique in each trigger firing.
No. The INSERTED and DELETED tables are the final (i.e. "after") state of the operation, in terms of FOR / AFTER triggers. For INSTEAD OF triggers, the INSERTED and DELETED tables are what would have been the final state. Well, the DELETED table is really the prior state of those rows whereas INSERTED is the current state.

foreign key data deletion should display error for primary key

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.

Delete from multiple tables SQL

I trying to figure out how I can delete from multiple tables in SQL Server.
I have one table containing only one primary key and three foreign keys for the three table I want to delete from. The other three table does not contain any foreign keys.
The stored procedure have one parameter, a specific primary key from one of the tables. I want to delete from the other tables WHERE tableID = #tableID. The constraints between the tables are set to cascade.
Is it possible with only that parameter to delete from all four tables?
I've tried with inner join, outer join, temptable..
Table Table Table Table
Pk Pk(Fk1) Pk(Fk2) Pk(Fk3)
Fk1 Column Column Column
Fk2 Column Column Column
Fk3
I have the table 2 Pk as parameter.
if your foreign keys were created with DELETE CASCADE, once you delete from the main table, all the related rows on the foreign tables will be delete too.
It seems like this is how it is configured, isnt it working?

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?

How to insert a new record to table A when table A deppends on table B and vice versa

I'm not sure if this is well designed, if it's not please, advice me on how to do this.
I'm using Sql Server 2008
I have:
TableA (TableA_ID int identity PK, Value varchar(10), TableB_ID PK not null)
TableB (TableB_ID int identity PK, Value varchar(10), TableA_ID PK not null)
The goal is simple:
TableA can have rows only if there is at least 1 row in TableB associated with TableA;
And for each row in TableB, there must be a row associated with it in TableA);
TableA is the "Parent Table", and TableB is the "Children's table", it's something like, a parent should have 1 or more children, and each child can have only 1 parent.
Is this right?
The problem I'm having is when I try to do an INSERT statement, if this is correct, how should I make the INSERT? temporary disable the constraints?
Thanks!
The problem I'm having is when I try to insert
TableA (TableA_ID int identity PK, Value varchar(10))
TableB (TableB_ID int identity PK, Value varchar(10), TableA_ID not null)
as a parent, table a does not need to reference table b, since table be requires there be a field in table a. this is called a one to many relationship.
so in table a you might have these values:
1 a
2 b
3 c
and in table b you could have these:
1 asdf 1
2 sdfg 1
3 pof 2
4 dfgbsd 3
now you can make a query to show the data from table a with this:
select b.TableB_ID, b.Value, a.TableA_ID, a.Value
from TableB b
inner join TableA
on b.TableA_ID=a.TableA_ID
The parents don't depend on the children. You need to remove your reference to Table B in Table A.
You have a circular dependency. These don't really work well for declarative enforcement, you would have to disable the constraints every time you wanted to insert.
That's an unusual requirement. If I was stuck with it (and I would really push back to make sure it was indeed a requirement) I would design it this way:
Make a regular foreign key from table a to table b with a the parent and b the child.
Add a trigger to table a that inserts a record to table b if one does not exist when a table a record is inserted. Add another trigger to table b that deletes the table a record if the last related record in table b is deleted.
ALternatively, you could put the inserts to both tables ina stored proc. Remove all insert rights to the table except through the proc. YOu would still need the foreign key relationship from tablea to table b and the trigger on table b to ensure that if the last record is deleted the table a record is deleted. But you could do away with the trigger on table a in this case.
I would use the first scenario unless there is information in table b that cannot be found from the trigger on table a, say one or more required fields that don't have a value you can figur eout form table a.
I would put the inserts into a proc: disable the constraints, insert the data, enable the constraints. You may need to make sure that this is the only transaction going on whilst the constraints are disabled though.
That could be acheived by making the isolation level SERIALIZABLE, but that in turn could massace your concurrency.
Kev

Resources