Delete records from multiple tables simultaneously? - sql

I have 4 tables. In first table has appid as primary key and in other three table its foreign key. I want to delete data from all the three in one query. I tried my best but failed. Can anybody help?

You cannot write a delete statement that references more than one table, you need to write 4 delete statements.
However, if appropriate, you can define the foreign keys on the 3 child tables to "ON DELETE CASCADE". Then when you delete from the parent table, all associated rows from the 3 child tables are also deleted. This can be useful sometimes, but I would not recommend it as a general practice as it can be dangerous and confusing for developers.

There is no way to delete from many tables with a single statement, but the better question is why do you need to delete from all tables at the same time? It sounds to me like you don't fully understand how transactions work in Oracle.
Lets say you login and delete a row from table 1, but do not commit. As far as all other sessions are concerned, that row has not been deleted. If you open another connection and query for the row, it will still be there.
Then you delete from tables 2, 3 and then 4 in turn. You still have not committed the transaction, so all other sessions on the database can still see the deleted rows.
Then you commit.
All at the same time, the other sessions will no longer see the rows you deleted from the 4 tables, even though you did the deletes in 4 separate statements.

If database is Mysql you can use join in DELETE statement.
See http://dev.mysql.com/doc/refman/5.0/en/delete.html for more info.

Related

On delete cascade with 2 different tables

I have the following case, what I would like to do is, if I delete a row from DashboardKpi or DashboardGrid, the corresponding record on ComponentProperty should be deleted as well.
Is this possible? So far, I was only able to do the other way around, if I delete a ComponentProperty, the corresponding DashboardKpi or DashboardGrid gets deleted, but this is definitely not what I want.
ER Diagram
Any suggestion on how can I do?
Delete cascade wont help you. As you mentioned when you delete row cascade it will delete all other rows in other tables those referencing to original deleting row, after that your original row.
The reason of logic is that rows in ComponentProperty can be without DashboardKpi or DashboardGrid, but rows in DashboardKpi or DashboardGrid (if they have reference to ComponentProperty) cant not cause they depend on ComponentProperty.
You could solve your problem in different ways depending on your DBMS. Common to most of them is to use procedures or triggers. If you use Postgresql then you can use ON DELETE rule as well.

SQL Server - The optimal way of running two DELETE statements using the same SELECT results

I need to delete entries from two tables, using some ids found from a unique SELECT query.
What is the most performant way of doing this using SQL Server?
I currently use a Table Variable :
DECLARE #emailIdsToDelete TABLE(id int NOT NULL);
INSERT INTO #emailIdsToDelete
SELECT id
FROM ...;
DELETE organisations_emails
FROM #emailIdsToDelete etd
INNER JOIN ...;
DELETE emails
FROM #emailIdsToDelete etd
INNER JOIN ...;
But since I need that table only to store the result of the SELECT, and only for the scope of this specific query, I was wondering if there was a more performant solution.
I think I can't use CTE (using the "with()" clause) since it allows only one following statement, not two.
Is there a way to delete from those two tables, without having to create a temporary table first? Some kind of join? Or is my solution already optimal?
UPDATE : Let's say there is no "ON DELETE CASCADE" between any of those tables.
Cascade Delete is an option, however you would need to test to validate it is more performant, also sometimes even with FKs this can leave orphans records.
Soft Delete You could add a isDeleteFlag column set it to bit default(0) and update it to 1 when you run your query, again would have to test it. If you wanted to stop there you would need to change your usp_ to accommodate not to return these records. where isDeleteFlag = 0
To follow up with the most performant, you could use the soft delete and then at night do smaller batches of deletes, or you could store the delete ids in a separate table and remove them at night in batches. This might work for you depending on what you are trying to accomplish, if it is okay to steal performance at night rather than during normal business operations, sometimes it's not viable.
In the end the answer is it depends and mileage will vary, you'll need to test the solutions to compare performance.
Optionally you could use your approach and use a variable table / temp table or a user defined table type.
Edit: Also you could output the deleted ids and daisy chain deletes in a transaction.
The other way would be to have a foreign key between organisations_emails and emails with ON DELETE CASCADE. Then you would merely need to delete from emails, and matching rows in organisations_emails would be deleted automatically.
Assuming that the foreign key is appropriate in your schema, of course.

Updating a database with keeping relationships

I've got a database which has some tables I want to keep up-to-date. I've got to write a SQL script that checks if there are certain rows in target tables and if there are not, insert them. I tried MERGE, but i have 8 tables related to the 9th one so there are 8 foreign keys and I don't know how to update them all. I don't want to delete all and insert again, because i want to save my main table rows' IDs.
You can use trigger that automatically add inserted rows to destination tables

How can I delete records from a table when there are foreign keys that depend on these records?

I have lots of tables that have foreign keyed to a PersonId column. I need to delete a person from the database.
If I do a simple:
DELETE FROM Persons WHERE PersonId=111
I get an error:
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_CIPerson". The conflict occurred in database "adb", table "CI", column 'Person_Id'.
I keep going "down the tree" of dependencies and delete from the roots. This has generally worked, until I got to a certain table where it won't let me delete any further. I believe I have to join 2 tables and delete the rows in BOTH tables that have my PersonId in it.
This join joins the tables in the way I want them to be joined:
SELECT *
FROM Table1
INNER JOIN Table2 ON Table1.anId = Table2.someId
This results in a joined table that has the PersonId (from Table2). I now want to delete all the rows where PersonId=111, so I need a where clause plonked in too.
Thanks in advance!
By definition, SQL DELETE statement only affects one table. If you need to cascade delete, you can simplify things by using #paqogomez suggestion: just specify ON DELETE CASCADE option on the foreign key declaration.
There are at least 3 solutions:
ON CASCADE DELETE
(As answered by Gerardo) If the problem is just foreign key constraints, then you can use this and deleting the person will do all the rest. But this may not always work. As usr said, there are some cases in which foreign keys are complex and mangled a bit.
BEFORE DELETE TRIGGER
You can define a trigger and activate it BEFORE DELETE on the person table. In the trigger you can take care of the deletion of dependent rows from other tables. This is similar to the ON CASCADE DELETE, but you have a little more control over how to perform the deletion... this may solve some of those complex problems.
STORED PROCEDURE
You can define a stored procedure with a person_id parameter. The code would be similar to the trigger's. But in stored procedures you can sometimes do some extras, like deactivating foreign keys (not sure about SQL Server though).
DELETION SCRIPT
This is the most powerful, as you can mix DDL and SQL and do all sorts of stuff. But scripts usually have to be run manually, which might not be acceptable in your case.

Sql Serve - Cascade delete has multiple paths

I have two tables, Results and ComparedResults.
ComparedResults has two columns which reference the primary key of the Results table.
My problem is that if a record in Results is deleted, I wish to delete all records in ComparedResults which reference the deleted record, regardless of whether it's one column or the other (and the columns may reference the same Results row).
A row in Results may deleted directly or through cascade delete caused by deleting in a third table.
Googling this could indicate that I need to disable cascade delete and rewrite all cascade deletes to use triggers instead. Is that REALLY nessesary? I'd be prepared to do much restructuring of the database to avoid this, as my main area is OO programming, and databases should 'just work'. It is hard to see, however, how a restructuring could help as I would just move the problem around... Or am I missing something?
I am also a bit at a loss as to why my initial construct should even be a problem for the Sql Server?!
Any comments welcome and much appreciated!
Anders, Denmark
Would it be possible to split the ComparedResults into two tables?
Edit:
You could then use a View to gather the results for showing? Or a join between the two tables?