deleting in tables in a specific order - sql

Hy,my question is how can i use a procedure in which i can delete data from one table and then from the other to avoid the problem with the REFERENTIAL INTEGRITY, I tried it like this
create procedure usp_Testovi_Delete
(
#TestoviID int
)
as
delete from Testovi
where TestoviID=#TestoviID
delete from RezultatiTesta
where TestoviID=#TestoviID
but I need to execute it twice to delete data from both tables , ty for your time and help , I'm using SQL server.

There are a variety of ways to handle this:
Delete from the table with the foreign key first.
Wrap the first delete in a blank exception handler, then delete from the second table, and finally delete from the first table again.
Disable the foreign keys while you perform the delete, and re-enable them afterward.
They each have advantages and disadvantages :-/

Related

How to delete items with a many-to-many relationship with 'WHERE' clause in a stored procedure?

In my MSSQL database I have the following three tables:
Tasks
Files
TaskFile
As one can imagine, TaskFile simply maps IDs of the Tasks table to the IDs of the Files table having foreign key constraints to them. I do most of my database operations using stored procedures. Deleting a single file by ID is then easy, I simply have to delete the entries in TaskFile first:
CREATE PROCEDURE [dbo].[spFile_Delete]
#ID INT = 0
AS
BEGIN
DELETE
FROM dbo.[TaskFile]
WHERE FileID = #ID;
DELETE
FROM dbo.[File]
WHERE ID = #ID;
END
However, I'm wondering what the recommended way is to delete multiple files. For example, file entries belong to a dataset and therefore hold a reference to a DatasetID. I have the following procedure to delete by DatasetID however this needs to be adapted to work with the foreign key constraint:
CREATE PROCEDURE [dbo].[spFile_DeleteByDataset]
#DatasetID NVARCHAR(128)
AS
BEGIN
DELETE
FROM dbo.[File]
WHERE DatasetID = #DatasetID;
END
The most straight forward way I can think of, is to first query all the FileIDs with the given DatasetID and then use them to delete all entries in TaskFile first. This should work, but doesn't seem like the best solution, especially if I want to go further and have for example have a stored procedure to delete datasets. Now I would have to:
Find all the files belonging to the dataset
Find all the references in TaskFile and delete dem
Delete all File entries
Delete the dataset entry
and for each relationship this would go further and further and get more and more complicated.
Basically I'm asking for some best practices in such cases. I'm fairly new when it comes to database management and these convolution seem like a good source for errors. Should each stored procedure only handle it's specific table and I have to manage the correct order of entries/updates/deletions in the data access layer code? Is there a way to automate changes with foreign relationships? Or should you simply never delete anything from the database and only have a flag 'deleted' in a separate column?
Oh I believe you are talking about DELETE/UPDATE CASCADE. It's usually not advised because in general you don't want to delete more than you are targeting in the moment. But depending on the scenario it can be used. For example in your case i believe it's ok: if FileTask has ON DELETE CASCADE in the reference to File, when you delete straight the table File, all FileTask related to this file would be deleted together and you wouldn't need to worry about deleting FileTask before. In your case when you want to delete a file, you also want to delete related FileTasks.

Delete Value with Relational Table Trigger vs

How do you delete values with a relational database for connected tables.
Example of Movie Database:
Movie Table -> Movie_has_Genre Table -> Genre Table
If I delete a Movie I would want to delete all the rows of Movie_has_Genre table where the foreign key is the same as the id from the movie table.
Should I be using a Trigger on the Movie table (on delete... do a delete on the relational table) or is there some other built in function to handle this?
I just vaguely recall there was another way to do this but cannot remember what it was called.
You use the cascade delete statement. It's syntax looks like this:
ALTER TABLE dbo.T2
ADD CONSTRAINT FK_T1_T2_Cascade
FOREIGN KEY (keyId) REFERENCES dbo.T1(keyId) ON DELETE CASCADE
The complete syntax is: here
There is an option in SQL Server to do this automatically via CASCADE settings as already shown.
This is a really handy option but make sure you don’t apply it to all of your tables that have foreign key references as it might cause unexpected loss of data. Make sure to thoroughly analyze weather this won’t cause any damage.
Another option is to use multiple delete statements starting from the tables that are referenced first.

How to validate data in sql server?

I have an issue related to data in sql server. In my database some of the constraint were not enabled i.e. they were not checked , After some time working on it we found this issue that a parent rows can be deleted without deleting child, which was an issue. I enabled all the constraint in the database using query
ALTER TABLE tbl_name CHECK CONSTRAINT ALL
above query was executed on all the tables of that database without any error . But my concern is whether it will work or not , if it will work on the existing data then what will happen to that data whose parent table data has been deleted.
I want to know is there any way such that I can validate such data data whose parent record doesn't exist in the entire database. There are about 270 constraint containing FOREIGN KEY AND UNIQUE KEY . I don't want to go for manual option.
Please help me out.
ALTER TABLE tbl_name CHECK CONSTRAINT ALL
only re-enables the constraints. Importantly, the constraints are not checked against the existing data in the database (nor are they trusted by the optimizer). If you want that to occur, you need to specify WITH CHECK as well:
ALTER TABLE tbl_name WITH CHECK CHECK CONSTRAINT ALL
(And yes, the word CHECK appears twice)
If you execute this, and there are orphaned child rows (or other invalid constraints), then the ALTER TABLE will fail with an error message. There's nothing SQL Server can do to fix this issue - it's for you to decide whether to a) remove the orphaned rows, or b) to re-create, in some manner, a suitable parent row for them.
You can also add the 'ON DELETE CASCADE' code to the end of foreign keys to prevent orphaned child rows from persisting.
This is more of a 'better practice' going forward than a solution, but I believe Damien_The_Unbeliever has answered your main question.

TRUNCATE TABLE query unable to execute in SSIS because of foreign key

I have a table Person which contains 2 fields.In my another database i have a Participant Table(also have 2 columns).From Participant Table i have to insert values into Person Table.
but before every insertion,i want truncate the person Table.
I have try it out with linking Execute Sql task to Data flow task.But it is showing error that a Primary Foreign key relation exists there.
If I understand correctly, SSIS has nothing to do with your real problem, which is that you want to truncate a table that is referenced by a foreign key constraint. That question has already been answered: Cannot truncate table because it is being referenced by a FOREIGN KEY constraint?
If a table in sql server has foreign key references then you can't truncate. instead in your execute sql task use delete without a where clause.
delete from person_table
If you are really adamant about truncating the table, you could drop the foreign key constraints, then truncate the table then recreate the foreign key constraints. Providing of course, that the user you are running the package as has the privileges to do so.
Create an "Execute SQl" task and run DELETE FROM person
after this task, run your import.
DELETE FROM will give the same result as TRUNCATE TABLE, but if the table has a foreign key pointing to it, it cant be truncated. You have to use the delete command
You won't be able to delete either unless cascading deletes is turned on (or you delete the child records first). Why is this a problem you ask, why can't I do what I want to do? Because if you do then you may lose the integrity of the data. Suppose I have records in table2 which relate to records in table 1. Suppose further that table1 has an autogenerated id. If I could truncate that table, then I leave those records i ntable 2 hanging out without any record to reference them, they have become orphaned. Well but I'm putting the data back in you say. But then they will have new id numbers and you will still lose the relatinoship tothe related data.
Can you drop the FK and truncate and insert and recreate the FK. Yes you can but it is a poor practice and you should not unless you are also recreating those related records.
The best practice is to use a MERGE statement to update or insert depending on what you need.
In SSIS Transfer SQL Server Objects Task Set Property DeleteFirst to TRUE

Before trigger in SQL Server

I have 2 tables: survey (id(PK), name) and survey_to_topic (survey_id(PK,FK,not null), topic_id(PK,FK,not null)). When I try to delete from survey table, I get exception:
"The DELETE statement conflicted with
the REFERENCE constraint
"FK_survey _to _topic _survey". The
conflict occurred in database
"mydatabase", table
"dbo.survey _to _topic", column
'survey _id'."
So to get no error first I must delete record from table survey_to_topic and after that from table survey. I think it is better to do with before trigger on table survey, but I can't find any information about this. There are a lot of articles about before triggers in PL/SQL, but I use SQL Server.
You can add ON DELETE CASCADE to the relationship between the two tables, and the records from the survey_to_topic table will be deleted automatically.
See http://msdn.microsoft.com/en-us/library/aa933119(SQL.80).aspx
You can use ON DELETE CASCADE. This is added to the table containing the FK.
See example here.
As Alex Deem and astander already mentioned - you should use ON DELETE CASCADE on your foreign key relationship - that handles this scenario automatically for you.
SQL Server doesn't know the concept of BEFORE (operation) TRIGGERs - SQL Server has AFTER triggers, or then INSTEAD OF triggers. See the Introduction to triggers article for some background info.
But ON DELETE CASCADE is definitely the easiest way to do this.
As everyone else here mentioned, ON DELETE CASCADE is a way to go -- as long as you are aware of consequences; there is a reason why ON DELETE NO ACTION (raise error) is the default. In other words, you should plan your deletion strategy -- it is too easy to wipe out rows from several tables unintentionally by using ON DELETE CASCADE.