Two tables share a unique identifier 'id'. Both tables are meant to be joined by using 'id'.
Defining 'id' as an auto incrementing primary key in both tables may risk update inconsistencies.
Is there some general pattern to avoid such a situation or do I have to deal with updating table1 first and table2 by utilizing the last inserted id after (therefore not declaring id as auto inc in table2)?
First, if you use InnoDB table engine in MySQL you could use both transactions and foreign keys for data consistency.
Second, after the insert in the first table, you could get the last insert id (depending on the way you access the db) and use it as foreign key.
Eg
Table 1: Users: user_id, username
Table 2: User_Profiles: user_id, name, phone
In User_Profiles you don't need to define user_id as auto increment, but first insert a record in Users table and use the user_id for the User_Profiles record. If you do this in transaction, the Users record won't be seen outside of the transaction connection until it's completed, this way you guarantee that even if something bad happens after you insert the user, but before you have inserted the profile - there won't be messed up data.
You could also define that the user_id column in User_Profiles table is foreign key of Users table thus if someone deletes a record from the Users table, the database would automatically delete the one in User_Profiles. There are many other options - read more about that.
There is no problem with same column name 'id' in any number of tables.
Several persistence layer frameworks do it same way.
Just use aliases in your SQL to distinct your tables accordingly.
do I have to deal with updating table1 first and table2 by utilizing the last inserted id after (therefore not declaring id as auto inc in table2)?
Yes. And make id a foreign key so it can only exist in table2 if it already exists in table1.
Yes you do, and remember to wrap the operation in a transaction.
Related
Scenario:
User A and B executes at the same time select id from Product where id = ?, if the there are no results, both create a new product with given ID.
Problem:
This could lead to the creation of duplicate rows.
Question:
What are the possibles strategies to prevent that? I know that I can use compound/unique keys, to guarantee this, but are there any other strategies? Is there any SQL statement to lock query with same parameters?
You can use unique constraints
ALTER TABLE Persons ADD UNIQUE (P_Id)
or
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName)
That way it would be impossible for a duplicate to be inserted.
Put a UNIQUE key on the field in question:
https://dev.mysql.com/doc/refman/5.0/en/constraint-primary-key.html
I have a table with name as listings and inside there I have a COLUMN namely as when some rows are deleted so the AUTO Incrmementation columns namely as "ID" goes into soemthing very bad values..Like missing values in between which I don't like and don't suit like a professional way..so therefore I want please if you people can guide me to how reset all ID columns values in rows on each INSERT or DELETE Query Exeution please..!
If you really want to find the lowest unused key value, don't use AUTO_INCREMENT at all, and manage your keys manually. However, this is NOT a recommended practice.
AS explained at Auto Increment after delete in MySQL
Primary autoincrement keys in database are used to uniquely identify a
given row and shouldn't be given any business meaning. So leave the
primary key as is and add another column called for example
courseOrder. Then when you delete a record from the database you may
want to send an additional UPDATE statement in order to decrement the
courseOrder column of all rows that have courseOrder greater than the
one you are currently deleting.
As a side note you should never modify the value of a primary key in a
relational database because there could be other tables that reference
it as a foreign key and modifying it might violate referential
constraints.
Well it is not recommended but you insisted , so use this to re order
By using something like:
ALTER TABLE table_name AUTO_INCREMENT = 1;
in DB tables i've: Patient Table, PatientBasicInfomation Table, PatientImageFindings Table..
i've multiple Questions depend on this design..(note that i'm beginner in DB)
1) if i have for each Patient an ID.. so according to DB concepts both PatientBasicInfomation, PatientImageFindings should have this key (ID) as a foreign key?!
2) in the Patient Table i should reference to the PatientBasicInfomation, PatientImageFindings by using their private keys so they will be in Patient Table as a foreign keys?! am i thinking correct...
3) Now my big problem: i want to insert in PatientImageFindings Table a record but under condition ID + Date (where Date is an important Field in PatientImageFindings Table, i don't know if i should put it as a private key or not..), how could i do this insertion statement in my java class..(Insertion under conditions)
What you want to do is add a UNIQUE constraint across multiple columns.
This question provides an answer to do just that:
How do I specify unique constraint for multiple columns in MySQL?
alter table votes add unique index(user, email, address);
Unless you have another reason, you should enforce this at the database level and treat exceptions as they arise after attempted INSERTs.
If I have 2 accounts table: saving account and overdraft account, and then I have the table transaction in which column "from_account" can only have value equal to either saving account ID or overdraft account ID, how should I set the foreign key constraint? Is there any better schema design as the saving&overdraft account ID can collide.
Im using mysql btw :)
Thanx
A better schema design would be to have two distinct columns in the transaction table: One referencing the saving account table and the other referencing overdraft account table. Of course, these columns should be nullable and only one of them will point to an actual row in the other tables. But with this design you can enforce referential integrity constraints.
Another option would be to merge the two account tables into one, especially if they have many similar columns.
You can define an additional column ACCOUNT_TYPE and set a UNIQUE CONSTRAINT combining the FROM_ACCOUNT and the ACCOUNT_TYPE columns. You can also add a CHECK CONSTRAINT to the ACCOUNT_TYPE to limit its values to i.e 1,2.
Or you define one column for each referenced table plus a CHECK CONSTRAINT to ensure you never fill both at the same time.
And finally, consider merging both account tables, if there is no much difference between them.
I am having my application deployed on two separate regions say US-WEST and EU, both application has its own DB. And now I want to move the EU region DB to US-WEST.
This will lead to primary key collision since both the db has the tables with same primary auto increment id, can anybody give me suggestion to solve this.
Scenario:
User Table from DB1(say from US-WEST) has the following entries
ID Name
1 Rob
2 San
3 Tulip
User Table from DB2(say from EU) has the following entries
ID Name
1 John
2 Michael
3 Natasha
For every one of the two original databases (say db0 and db1):
Back up the db.
Lock database for use by this script only.
For all the tables in the database that have foreign keys defined without ON UPDATE CASCADE, change all these foreign keys constraints with this option.
For every table with an auto_increment (or a simple integer) Primary Key, run this (the cascading updates will make the rest):
.
UPDATE TableX
SET Pk = 2 * Pk - 0 --- for db0
ORDER BY Pk DESC
UPDATE TableX
SET Pk = 2 * Pk - 1 --- for db1
ORDER BY Pk DESC
Export the tables from each database.
Now merge the two databases by simply merging the corresponding tables. All data from db0 will have even ids and all from db1 will have odd ids. No collisions.
For tables without auto-incrementing Primary Keys or for tables which may have common rows, the merging should be different, off course.
Unlock.
You can read about auto_increment_increment and related system variables that you can change so from this point, the two databases produce different auto incremented ids (one odd ids, the other even ones).
Turn off auto-increment in your destination DB. Then first import data from DB1 and the from DB2. In your importing from DB2 add a constant value that is higher than your hightest id in the first DB. Like this:
insert into destination_table
select id + 10000, othercolumns from source_table
After importing the data you can turn on auto-increment again.
EDIT :
If your id column references to other tables then this method will break the relation to these tables.
I think you have to extend your destination DB with a column for example regionID and edit the primary key settings for this table. Use a Primary key with the two columns ID and regionID. Then import the data from the two tables like this:
Insert into destination_table values(regionID, ID, Name)
select 1,ID, Name from DB1
Insert into destination_table values(regionID, ID, Name)
select 2,ID, Name from DB2
Now, the tricky part. You have to do this for all tables, where you use the ID as a relation. After transferring all data you only have to edit your SQL statements to use regionID and ID combined as key.
Remove primery key and Turn off auto-increment from id field your destination DB table.
Then first import data from from both DB.
Delete id column from destination table.
Create again id column make that column auto increament primary key.