deleting from two tables in single script in sql - sql

I have three tables xx_1 , xx_2, xx_3 such that :
xx_1
id obj_version_num location
1 x ubudu
2 x bali
3 x india
xx_2
id name grade
1 abc band 1
2 xyz band 2
3 gdgd band 3
xx_3 has :
Name details col1 p_id
abc A HDHD 10
xyz B HDHD 20
gdgd C HDHD 30
smith D HDHD 40
I want to delete data from xx_1 and xx_2 if the name is smith in xx_3
Currently i am doing :
delete from xx_1
where id in (select distinct id from xx_2 t ,xx_3 k
where t.name=k.name
and k.name ='Smith')
and then
delete from xx_2
where name ='Smith'
Is there anyway i can delete data from both these table together ? without creating two separate scripts ?

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.
EDIT after edit in question:
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.

You cannot delete from multiple tables in a single statement, primary key or not.

Related

Conditional Column on sql

I'm trying to create a new table on my DB, the table has 2 important columns
id_brands (This is an FK from the table brands)
id_veiculo
What I would like to have is something like this:
id_brands
id_veiculo
1
1
1
2
2
1
2
2
3
1
1
3
3
2
I create the table but I'm trying to find a way to make this condition with a trigger but without success, I don't know if it's possible or if a trigger is the best way to do that.
What you are probably trying to do, by the pattern of the example table, is setting up an auxiliary N to N relationship table.
In this case, by having another table, for id_veiculo and its properties, you will be able to have both ids as FKs. As for the primary key in this auxiliary table, it would be both id_brands and id_veiculo:
PRIMARY KEY (id_veiculo, id_brands);
Here's another Stackoverflow question about NxM/NxN relationships.
Also, it isn't very clear what you're trying to do with the table, but if it's the population/seeding of data, then yes, a Trigger is an viable solution.

How save is it to delete rows with a query in the where clause

I have an object Head (table Head) which can have 0 or n positions (table Position).
HEAD table
HEAD_ID NAME
1 A
2 B
POSITION table
HEAD_ID POS_ID VALUE
1 1 X
1 2 Y
2 1 Z
3 1 DELETE ME
Unfortunately it is not possible to create foreign keys to maintain the data integrity. Therefore I want to create a delete script to delete Positions which do not have a corresponding head.
My delete script
DELETE POSITION
WHERE HEAD_ID NOT IN (SELECT HEAD_ID FROM HEAD)
Question: How does the command work if rows are inserted during the execution of the delete script into the tables? In my scenario both tables have several 10.000 of rows and the search may take some time.
If I understand it correctly, the list of HEAD_IDs from HEADS is created once at the beginning of the command. Therefore newly added rows will not be in the list and will be deleted. Is that correct?
The command would delete the position with HEAD_ID = 3 and POSITION_ID = 1 on my example, since the head is missing.
But how does it work, if after the SELECT and before the DELETE, new entries will be added to the both tables:
HEAD table
HEAD_ID NAME
1 A
2 B
4 NEW HEAD
POSITION table
HEAD_ID POS_ID VALUE
1 1 X
1 2 Y
2 1 Z
3 1 DELETE ME
4 1 WILL I BE DELETED?
Will the new position with the HEAD_ID = 4 and POSITION_ID = 1 be deleted since the head was not in the SELECT?
Any way to do perform the task in a safer way?
You can use MySQL table locking feature for you delete operation, then no new data will insert until your delete operation finish.
First Lock the tables
LOCK TABLES table_name WRITE
Then do your delete operation and after release the table lock
UNLOCK TABLES;
MySQL allows a client session to explicitly acquire a table lock for preventing other sessions from accessing the same table during a specific period.
A client session can acquire or release table locks only for itself. And a client session cannot acquire or release table locks for other client sessions.
Ref : https://www.mysqltutorial.org/mysql-table-locking/

delete from database when certain string occurs n times

I have a database with table a with column b.
b
1 a-b
2 a
3 a-b-c
how can I delete all rows from the table where - occurs more than once?
Use like:
delete from t
where b like '%-%-%';

SQL Server "pseudo/synthetic" composite Id(key)

Sorry but I don't know how to call in the Title what I need.
I want to create an unique key where each two digits of the number identify other table PK. Lets say I have below Pks in this 3 tables:
Id Company Id Area Id Role
1 Abc 1 HR 1 Assistant
2 Xyz 2 Financial 2 Manager
3 Qwe 3 Sales 3 VP
Now I need to insert values in other table, I know that I may do in 3 columns and create a Composite Key to reach integrity and uniqueness as below:
Id_Company Id_Area Id_Role ...Other_Columns.....
1 2 1
1 1 2
2 2 2
3 3 3
But I was thinking in create a single column where each X digites identify each FK. So the above table 3 first columns become like below (suposing each digit in an FK)
Id ...Other_Columns.....
121
112
222
333
I don't know how to call it and even if it's stupid but it makes sense for me, where I can select for a single column and in case of need some join I just need to split number each X digits by my definition.
It's called a "smart", "intelligent" or "concatenated" key. It's a bad idea. It is fragile, leads to update problems and impedes the DBMS. The DBMS and query language are designed for you to describe your application via base tables in a straightforward way. Use them as they were intended.

How to merge two identical database data to one?

Two customers are going to merge. They are both using my application, with their own database. About a few weeks they are merging (they become one organisation). So they want to have all the data in 1 database.
So the two database structures are identical. The problem is with the data. For example, I have Table Locations and persons (these are just two tables of 50):
Database 1:
Locations:
Id Name Adress etc....
1 Location 1
2 Location 2
Persons:
Id LocationId Name etc...
1 1 Alex
2 1 Peter
3 2 Lisa
Database 2:
Locations:
Id Name Adress etc....
1 Location A
2 Location B
Persons:
Id LocationId Name etc...
1 1 Mark
2 2 Ashley
3 1 Ben
We see that person is related to location (column locationId). Note that I have more tables that is referring to the location table and persons table.
The databases contains their own locations and persons, but the Id's can be the same. In case, when I want to import everything to DB2 then the locations of DB1 should be inserted to DB2 with the ids 3 and 4. The the persons from DB1 should have new Id 4,5,6 and the locations in the person table also has to be changed to the ids 4,5,6.
My solution for this problem is to write a query which handle everything, but I don't know where to begin.
What is the best way (in a query) to renumber the Id fields also having a cascade to the childs? The databases does not containing referential integrity and foreign keys (foreign keys are NOT defined in the database). Creating FKeys and Cascading is not an option.
I'm using sql server 2005.
You say that both customers are using your application, so I assume that it's some kind of "shrink-wrap" software that is used by more customers than just these two, correct?
If yes, adding special columns to the tables or anything like this probably will cause pain in the future, because you either would have to maintain a special version for these two customers that can deal with the additional columns. Or you would have to introduce these columns to your main codebase, which means that all your other customers would get them as well.
I can think of an easier way to do this without changing any of your tables or adding any columns.
In order for this to work, you need to find out the largest ID that exists in both databases together (no matter in which table or in which database it is).
This may require some copy & paste to get a lot of queries that look like this:
select max(id) as maxlocationid from locations
select max(id) as maxpersonid from persons
-- and so on... (one query for each table)
When you find the largest ID after running the query in both databases, take a number that's larger than that ID, and add it to all IDs in all tables in the second database.
It's very important that the number needs to be larger than the largest ID that already exists in both databases!
It's a bit difficult to explain, so here's an example:
Let's say that the largest ID in any table in both databases is 8000.
Then you run some SQL that adds 10000 to every ID in every table in the second database:
update Locations set Id = Id + 10000
update Persons set Id = Id + 10000, LocationId = LocationId + 10000
-- and so on, for each table
The queries are relatively simple, but this is the most work because you have to build a query like this manually for each table in the database, with the correct names of all the ID columns.
After running the query on the second database, the example data from your question will look like this:
Database 1: (exactly like before)
Locations:
Id Name Adress etc....
1 Location 1
2 Location 2
Persons:
Id LocationId Name etc...
1 1 Alex
2 1 Peter
3 2 Lisa
Database 2:
Locations:
Id Name Adress etc....
10001 Location A
10002 Location B
Persons:
Id LocationId Name etc...
10001 10001 Mark
10002 10002 Ashley
10003 10001 Ben
And that's it! Now you can import the data from one database into the other, without getting any primary key violations at all.
If this were my problem, I would probably add some columns to the tables in the database I was going to keep. These would be used to store the pk values from the other db. Then I would insert records from the other tables. For the ones with foreign keys, I would use a known value. Then I would update as required and drop the columns I added.