mysql inserting with foreign key - mysql

i do have a form field which includes values which will be put in different tables in mysql.
they are all connected with foreign keys.
how do i put these values to different tables.
pseudo tables:
users_table:
userId|userlogin
user_info:
info_id|userId|name|surname
user_contact:
contact_id|userId|phone|email
form includes:
userlogin
name
surname
phone
email
in my research, i found out that i can use mysql_insert_id to link the FKs, but i wonder if that can cause problems if there is high load in the website (diff. requests sent at the same time).
i also found out that i can set triggers to create new fk values:
CREATE TRIGGER ins_kimlik AFTER INSERT ON hastalar
for each row
insert into hasta_kimlik set idhasta = new.idhasta
but i don't know how to add data to them. i can use
UPDATE table SET (name, surname) VALUES ('John', 'Brown') WHERE info_id = LAST_INSERT_ID();
but it doesn't feel the native way.
what is the best practise?

i found out that i can use mysql_insert_id to link the FKs, but i wonder if that can cause
problems if there is high load in the website (diff. requests sent at the same time).
mysql_insert_id returns the last auto-increment value generated by the database connection currently in use.
It doesn't matter what other processes do on other connections. It is safe. You'll get the right value.
but it doesn't feel the native way.
nope. The right way is :
INSERT user
get id
INSERT user_info

If the tables are connected by foreign keys shouldn't you just start with the basic table (users_table here) and then add in either user_info table and then in user_contact table, or the other way around. As long as you have filled in the table that has the primary key of the fk's in the other tables, then you can add easily.
INSERT SQL command:
INSERT INTO table_name (column1, column2, column3,...) VALUES (value1,
value2, value3,...)
Is that what you were asking?

Related

How can I add information to multiple tables simultaneously while having corresponding keys?

I am wanting to create a new user accounts on my web app while inserting data into multiple tables simultaneously in mysql. For example, I may have a table for general user information like authentification, while I may have another table that may have biography information for that user. A foreign key in the biography column must correspond to the primary key of the authentication table.
The user will fill out all that information in one form, but the information gathered will be placed in two seperate tables. The issue I am having is generating those tables in a way where those keys correspond, especially if I generate them at the same time.
Another example, I have a table with a list of restaurants called 'dining_listings'. One of those rows has a listing of 'All Foods Cuisine'. I may have a separate table called 'location_dining_types' listing all the food types that may correspond with that restaurant, with a foreign key corresponding to the primary key of that restaurant. There may be multiple rows in the 'locatiom_dining_types' table.
Also, I am wanting to generate a unique, primary key of various characters for each user. Instead of the standard auto_incrememt primary key, which by default starts at 1 and increments, I would like to generate a unique key of random characters, like fh4jnx68g4.
You need LAST_INSERT_ID()
Try something like this:
INSERT INTO user (given, surname) VALUES ('Michael', 'Widenius');
SET #userId =: LAST_INSERT_ID();
INSERT INTO company(user_id, name) VALUES (#userId, 'MySQL AB');
INSERT INTO company(user_id, name) VALUES (#userId, 'MariaDB Corporation AB');
LAST_INSERT_ID gives you the autoincrementing ID value from, well, the last insert. You then save it in a user defined variable and then use it to populate the FK values in other tables.
This is safe even if you have a lot of programs doing inserts because the LAST_INSERT_ID value is maintained per database connection.
If you want to generate the value yourself, you can do this sort of thing.
SET #userId = SELECT <<<random string>>
INSERT INTO user (user_id, given, surname) VALUES (#userId, 'Michael', 'Widenius');
INSERT INTO company(user_id, name) VALUES (#userId, 'MySQL AB');
INSERT INTO company(user_id, name) VALUES (#userId, 'MariaDB Corporation AB');
You want to know how to generate a random string in MySQL query language? Look here. Generating a random & unique 8 character string using MySQL
Caution: random strings as primary or foreign keys are harder to index efficiently than autoincrementing integers.

SQL - insert data into Parent and child table with attribute from parent table together

I have made 2 separate tables namely userlogin and userprofile with the following columns.
userlogin:
id
uname
pass
userprofile:
user_id(Foreign key)
name
gender
aboutme
Since i Will be taking some of the userprofile data at signup i was wondering what would be the best way to give the newly generated id from the userlogin table to the userprofile table.
I thought of making both insert queries right after one another but what if multiple users are signing up at the same time and one users login is saved with another users profile.
Should i instead go with saving the profiles foreign keyed with username?
If you worry about "simultaneous" sign up, you can use mysql transactions.
start transaction; then commit;
Example:
http://www.mysqltutorial.org/mysql-transaction.aspx
For the insertion with foreign key see this question: https://dba.stackexchange.com/questions/46410/how-do-i-insert-a-row-which-contains-a-foreign-key
Using a transaction is good, but there is probably another thing to point out here.
If id is AUTO_INCREMENT, then
INSERT INTO userlogin (uname, pass) VALUES (..., ...) -- without specifying id.
Get LAST_INSERT_ID() -- this gives you the value, and it is specific to your connection. That is no other connection can sneak in and grab your id.
Use that value for doing INSERT INTO userprofile (user_id, ...) VALUES ($id, ...)
Is there some reason for not combining the two tables? 1:1 relationships are rarely useful. as discussed here .

Creating single insert query for 3 tables in MySQL

I have three tables in a MySQL database, the tables are labeled address, employee, and login_info. address and employee have a one to one identifying relationship with a foreign key with login_info table. I would like to write a single sql query that would populate all three tables at the same and use the PK from the login_info table as the foreign key in both the employee and address table. How would I go about doing this, below are the column descriptions for the three tables I have. Thanks in advance for any help or suggestion.
You can try this structure, mate:
START TRANSACTION;
-- INSERT BLOCK FOR login_info
-- GET THE NEEDED KEY FROM login_info LAST INSERT
-- INSERT BLOCK FOR employee
-- INSERT BLOCK FOR address
COMMIT;
This is not the single-query answer you are expecting, but this may satisfy your need for your module. Using MySQL's TRANSACTION makes it either everything is executed or nothing changes. The 'A' in the ACID characteristic of MySQL.

Inserting Persons with IDs in one query?

I need to add data to a MySQL database like that:
Person:
pId, nameId, titleId, age
Name:
nameId, name
Title:
titleId, title
I don't want to have any names or title more then once in the db so I didn't see a solution with LAST_INSERT_ID()
My approach looks like that:
INSERT IGNORE INTO Name(name) VALUES ("Peter");
INSERT IGNORE INTO Title(title) VALUES ("Astronaut");
INSERT INTO Person(nameId, titleId, age) VALUES ((SELECT nameId FROM Name WHERE name = "Peter"), (SELECT nameId FROM Name WHERE name = "Astronaut"), 33);
But I guess that's a quite dirty approach!?
If possible I want to add multiple persons with one query and without having anything more then one times in db.
Is this possible in a nice way? Thanks!
You could put title and name as two columns of your table and then:
set one UNIQUE index on each column if you don"t want to have two titles or two names identical in the DB
or set an UNIQUE index on (title,name) if you don't want to have two entries having both the same name and the same title.
If you really want to have separate tables, you could do as you suggested in your post, but wrapping all your insert statements in a TRANSACTION to allow rollback if you detect a duplicate somewhere.
See Design dilemma: If e-mail address already used, send e-mail "e-mail address already registered", but can't because can't add duplicate to table which appear to be exactly the same problem, but having name & email instead of name & titles.
START TRANSACTION;
INSERT INTO title(value) VALUES ("Prof.");
SELECT LAST_INSERT_ID() INTO #title_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO username(value) VALUES ("Sylvain");
SELECT LAST_INSERT_ID() INTO #username_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO account(username_id, email_id) VALUES (#username_id,#title_id);
COMMIT;
See LAST_INSERT_ID()
A third solution would be to SELECT before doing you insert to see in the entry are already present. But personally I wouldn't push to the check-before-set approach at the very least, this will require an extra query which is mostly superfluous if you use correctly indexes.

Increment a database field by 1

With MySQL, if I have a field, of say logins, how would I go about updating that field by 1 within a sql command?
I'm trying to create an INSERT query, that creates firstName, lastName and logins. However if the combination of firstName and lastName already exists, increment the logins by 1.
so the table might look like this..
firstName----|----lastName----|----logins
John Jones 1
Steve Smith 3
I'm after a command that when run, would either insert a new person (i.e. Tom Rogers) or increment logins if John Jones was the name used..
Updating an entry:
A simple increment should do the trick.
UPDATE mytable
SET logins = logins + 1
WHERE id = 12
Insert new row, or Update if already present:
If you would like to update a previously existing row, or insert it if it doesn't already exist, you can use the REPLACE syntax or the INSERT...ON DUPLICATE KEY UPDATE option (As Rob Van Dam demonstrated in his answer).
Inserting a new entry:
Or perhaps you're looking for something like INSERT...MAX(logins)+1? Essentially you'd run a query much like the following - perhaps a bit more complex depending on your specific needs:
INSERT into mytable (logins)
SELECT max(logins) + 1
FROM mytable
If you can safely make (firstName, lastName) the PRIMARY KEY or at least put a UNIQUE key on them, then you could do this:
INSERT INTO logins (firstName, lastName, logins) VALUES ('Steve', 'Smith', 1)
ON DUPLICATE KEY UPDATE logins = logins + 1;
If you can't do that, then you'd have to fetch whatever that primary key is first, so I don't think you could achieve what you want in one query.
This is more a footnote to a number of the answers above which suggest the use of ON DUPLICATE KEY UPDATE, BEWARE that this is NOT always replication safe, so if you ever plan on growing beyond a single server, you'll want to avoid this and use two queries, one to verify the existence, and then a second to either UPDATE when a row exists, or INSERT when it does not.
You didn't say what you're trying to do, but you hinted at it well enough in the comments to the other answer. I think you're probably looking for an auto increment column
create table logins (userid int auto_increment primary key,
username varchar(30), password varchar(30));
then no special code is needed on insert. Just
insert into logins (username, password) values ('user','pass');
The MySQL API has functions to tell you what userid was created when you execute this statement in client code.
I not expert in MySQL but you probably should look on triggers e.g. BEFORE INSERT.
In the trigger you can run select query on your original table and if it found something just update the row 'logins' instead of inserting new values.
But all this depends on version of MySQL you running.