Update Record If Exists (Without Key) If Not Insert - mysql

Suppose I have a table user_keys with id, username, key. I need a query which will receive two parameters: username, key. I want to update record (only column key) if it exists (means that record with the incoming username already exists) if not then just insert new row with both parameters.
Well, I have tried a few things, here is one of them
if not exists (select * from user_keys where username='uname') then
insert into user_keys
(username, token)
values( 'uname','token')
else
update...
But it does not work. Any idea how to achieve?

Related

MYSQL Automatic INSERT ID in a different table

I am trying to learn some new things in MYSQL with PHPMyAdmin and I am wondering if the following thing is possible and how to get that to work. I'll try to explain it plain.
I have two tables
Table 1 = users & has
userID
username
etc.
Table 2 = users_permission & has
id
userID
is_admin
Now my idea was when I create record in table 1 by using an relation to table 2. It will automatically insert userID in Table 2 and create record based on default values. Is there someone who can help to get on track?
you need to make insertion for both tables seperately.
You first need to insert user into users table after that you need to insert into user permissions.
insert into users (userId, username) values( 1, 'JohnDoe');
insert into user_permission (id, userId, isAdmin) values (10, 1, 1);
For auto incremented ID column
insert into users (username) values('JohnDoe');
insert into user_permission (userId, isAdmin) values (LAST_INSERT_ID(), 1);

Insert row if there isn't already a row with the same id and url (two column values)

I would like to write a SQL statement that inserts a new row into the database if there isn't already a row for it. The unique identifier of a row is the id and url. Let's say the table schema looks like this:
LinkClicks: (id, url, clicks)
So now let's say I've got a row with a parameterized SQL insert. I'm attempting to do something like this:
INSERT (id, url, clicks)
INTO LinkClicks Values(#id, #url, #clicks)
WHERE #url NOT IN
(SELECT url FROM LinkClicks WHERE id=#id);
I think you want something like this:
INSERT INTO LinkClicks(id, url, clicks)
SELECT id, url, clicks
FROM (SELECT #id as id, #url as url, #clicks as clicks) t
WHERE t.url NOT IN (SELECT url FROM LinkClicks WHERE id = #id);
You can add a unique index on the id and url columns:
ALTER TABLE LinkClicks ADD UNIQUE u_idx (id, url);
With this constraint in place, attempts to insert a record whose id and url combination of values already appears will fail at the database level.
This might be preferable to the query you are attempting, because it guarantees that MySQL will reject a duplicate attempt to insert. A query could also be used to this effect, but later on perhaps someone else using your code base might forget this.
In fact you should take Tim's advice and put the unique index on the table but in doing so you need a fail safe way of ensuring that you don't attempt to put duplicates (id and url) into the table (otherwise loads of red-ink messages). This way seems ok:
DROP TABLE LINKCLICKS
DROP TABLE LINKCLICKS1
CREATE TABLE LINKCLICKS
(
[ID] INT,
[URL] CHAR(11),
CLICKS BIGINT
)
GO
INSERT INTO LINKCLICKS VALUES (1001,'www.abc.com',40000)
INSERT INTO LINKCLICKS VALUES (1002,'www.def.com',40000)
INSERT INTO LINKCLICKS VALUES (1003,'www.ghi.com',40000)
GO
CREATE TABLE LINKCLICKS1
(
[ID] INT,
[URL] CHAR(11),
CLICKS BIGINT
)
GO
INSERT INTO LINKCLICKS1 VALUES (1001,'www.abc.com',40000)
INSERT INTO LINKCLICKS1 VALUES (1003,'www.def.com',40000)
INSERT INTO LINKCLICKS1 VALUES (1004,'www.ghi.com',40000)
GO
WITH CTE1 AS
(
SELECT *,'d' AS [Source] FROM LINKCLICKS
UNION ALL
SELECT *,'s' AS [Source] FROM LINKCLICKS1
)
,
CTE2 AS
(
SELECT ID,[URL] FROM CTE1 GROUP BY ID,[URL] HAVING COUNT(ID) =1 AND COUNT([URL]) =1
)
INSERT INTO LINKCLICKS
SELECT ID,[URL],CLICKS
FROM CTE1
WHERE [Source] <> 'd'
AND
(
ID IN (SELECT ID FROM CTE2) AND [URL] IN (SELECT [URL] FROM CTE2)
)
SELECT * FROM LINKCLICKS ORDER BY [ID],URL
GO
The INSERT statement only inserts those rows where the ID and URL combined are not the same as rows already in the destination table. It quite happily inserts rows where either the IDs are the same but the URLs are different or where the IDs are different but the URLs are the same.
My only reservation is the question of 'dupes' in the source table (in this case LINKCLICKS1). If there are duplicates in the source table, none of them will be inserted into the destination table. This will defeat the object of the query.
The answer is, if you have duplicates, or any risk of duplication in the source table, then you should apply 'de-dupe code' to the source table before you run this.
If you need any de-dupe code, put a comment below.

mysql insert and select all at once

I am new to MySQL so bear with me please. I have set up a member table and a session table. When insert a new record in member table, session table will grab the assigned new record ID from member table and automatically insert into session table. Is this possible?
so the order will be something like:
insert new record(member table) -> fetch id(member table) -> insert new record(session table)
-I have already set up a foreign key in session table, but I don't know what to do
-Im using php, if this matter..
easily you can use LAST_INSERT_ID();
your query can be like this:
INSERT INTO members (id, name)
VALUES('', 'test');
INSERT INTO sessions (member_id, description)
VALUES(LAST_INSERT_ID(),'some description');
in this case id is set auto increment.
at the moment you insert your data into member table by using (LAST_INSERT_ID) the last inserted id will store in session table.

I need a logic to implement Mysql query

I have a 3 tables:
1. Users -- here "userd id" is primary key
2. UserPermision --here "userd id" is a foreign key and there is "pageid" coloumn
3. Page -- here page id is a primary key
Now i need to write a query when i inser a new user say user id = "1" then this user id 1 should be inserted into Userpermision table and for this user it shouls have all the pages from page table .
I'm assuming you are using InnoDB.
In that case you have foreign key constraints and transactions.
If not you'll have to use triggers.
START TRANSACTION;
INSERT INTO users (name, etc) VALUES ('test', 'remainder');
SELECT last_insert_id() INTO #my_user_id;
INSERT INTO userpermission (userid, permission, pageid)
SELECT
#my_user_id as user_id
, 'all' as permission
, pageid
FROM pages
WHERE pages.userid = #my_user_id;
COMMIT;
This is assuming you've already made pages for that user.
link
http://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
You need two INSERT queries, one for each table.
INSERT INTO Users (user_id,...) VALUES (:user_id,...)
INSERT INTO UserPermission (user_id,page_id)
SELECT :user_id, page_id FROM Page
You can either execute them within the same transaction, or execute the second one from the AFTER INSERT trigger on the Users table.

MySQL Insert into multiple tables? (Database normalization?) [duplicate]

This question already has answers here:
Insert into multiple tables in one query
(6 answers)
Closed 1 year ago.
I tried searching a way to insert information in multiple tables in the same query, but found out it's impossible?
So I want to insert it by simply using multiple queries i.e;
INSERT INTO users (username, password) VALUES('test', 'test')
INSERT INTO profiles (userid, bio, homepage) VALUES('[id of the user here?]','Hello world!', 'http://www.stackoverflow.com')
But how can I give the auto-increment id from the users to the "manual" userid for the profile table?
No, you can't insert into multiple tables in one MySQL command. You can however use transactions.
BEGIN;
INSERT INTO users (username, password)
VALUES('test', 'test');
INSERT INTO profiles (userid, bio, homepage)
VALUES(LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com');
COMMIT;
Have a look at LAST_INSERT_ID() to reuse autoincrement values.
You said "After all this time trying to figure it out, it still doesn't work. Can't I simply put the just generated ID in a $var and put that $var in all the MySQL commands?"
Let me elaborate: there are 3 possible ways here:
In the code you see above. This
does it all in MySQL, and the
LAST_INSERT_ID() in the second
statement will automatically be the
value of the autoincrement-column
that was inserted in the first
statement.
Unfortunately, when the second statement itself inserts rows in a table with an auto-increment column, the LAST_INSERT_ID() will be updated to that of table 2, and not table 1. If you still need that of table 1 afterwards, we will have to store it in a variable. This leads us to ways 2 and 3:
Will stock the LAST_INSERT_ID() in
a MySQL variable:
INSERT ...
SELECT LAST_INSERT_ID() INTO #mysql_variable_here;
INSERT INTO table2 (#mysql_variable_here, ...);
INSERT INTO table3 (#mysql_variable_here, ...);
Will stock the LAST_INSERT_ID() in a
php variable (or any language that
can connect to a database, of your
choice):
INSERT ...
Use your language to retrieve the LAST_INSERT_ID(), either by executing that literal statement in MySQL, or using for example php's mysql_insert_id() which does that for you
INSERT [use your php variable here]
WARNING
Whatever way of solving this you choose, you must decide what should happen should the execution be interrupted between queries (for example, your database-server crashes). If you can live with "some have finished, others not", don't read on.
If however, you decide "either all queries finish, or none finish - I do not want rows in some tables but no matching rows in others, I always want my database tables to be consistent", you need to wrap all statements in a transaction. That's why I used the BEGIN and COMMIT here.
fairly simple if you use stored procedures:
call insert_user_and_profile('f00','http://www.f00.com');
full script:
drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varchar(32) unique not null
)
engine=innodb;
drop table if exists user_profile;
create table user_profile
(
profile_id int unsigned not null auto_increment primary key,
user_id int unsigned not null,
homepage varchar(255) not null,
key (user_id)
)
engine=innodb;
drop procedure if exists insert_user_and_profile;
delimiter #
create procedure insert_user_and_profile
(
in p_username varchar(32),
in p_homepage varchar(255)
)
begin
declare v_user_id int unsigned default 0;
insert into users (username) values (p_username);
set v_user_id = last_insert_id(); -- save the newly created user_id
insert into user_profile (user_id, homepage) values (v_user_id, p_homepage);
end#
delimiter ;
call insert_user_and_profile('f00','http://www.f00.com');
select * from users;
select * from user_profile;
What would happen, if you want to create many such records ones (to register 10 users, not just one)?
I find the following solution (just 5 queryes):
Step I: Create temporary table to store new data.
CREATE TEMPORARY TABLE tmp (id bigint(20) NOT NULL, ...)...;
Next, fill this table with values.
INSERT INTO tmp (username, password, bio, homepage) VALUES $ALL_VAL
Here, instead of $ALL_VAL you place list of values: ('test1','test1','bio1','home1'),...,('testn','testn','bion','homen')
Step II: Send data to 'user' table.
INSERT IGNORE INTO users (username, password)
SELECT username, password FROM tmp;
Here, "IGNORE" can be used, if you allow some users already to be inside. Optionaly you can use UPDATE similar to step III, before this step, to find whom users are already inside (and mark them in tmp table). Here we suppouse, that username is declared as PRIMARY in users table.
Step III: Apply update to read all users id from users to tmp table. THIS IS ESSENTIAL STEP.
UPDATE tmp JOIN users ON tmp.username=users.username SET tmp.id=users.id
Step IV: Create another table, useing read id for users
INSERT INTO profiles (userid, bio, homepage)
SELECT id, bio, homepage FROM tmp
have a look at mysql_insert_id()
here the documentation: http://in.php.net/manual/en/function.mysql-insert-id.php
try this
$sql= " INSERT INTO users (username, password) VALUES('test', 'test') ";
mysql_query($sql);
$user_id= mysql_insert_id();
if(!empty($user_id) {
$sql=INSERT INTO profiles (userid, bio, homepage) VALUES($user_id,'Hello world!', 'http://www.stackoverflow.com');
/* or
$sql=INSERT INTO profiles (userid, bio, homepage) VALUES(LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com'); */
mysql_query($sql);
};
References
PHP
MYSQL
Just a remark about your saying
Hi, I tried searching a way to insert information in multiple tables in the same query
Do you eat all your lunch dishes mixed with drinks in the same bowl?
I suppose - no.
Same here.
There are things we do separately.
2 insert queries are 2 insert queries. It's all right. Nothing wrong with it. No need to mash it in one.
Same for select. A query must be sensible and do its job. That's the only reasons. Number of queries is not.
There is no point in looking for a way to stuff different queries in one call. Different calls is how the database API is meant to work.
For PDO You may do this
$dbh->beginTransaction();
$stmt1 = "INSERT INTO users (username, password) VALUES('test', 'test')";
$stmt2 = "INSERT INTO profiles (userid, bio, homepage) VALUES('LAST_INSERT_ID(),'Hello world!', 'http://www.stackoverflow.com')";
$sth1 = $dbh->prepare($stmt1);
$sth2 = $dbh->prepare($stmt2);
$sth1->execute (array ('test','test'));
$sth2->execute (array ('Hello world!','http://www.stackoverflow.com'));
$dbh->commit();