What is the equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?
This is what you are looking for:
LAST_INSERT_ID()
In response to the OP's comment, I created the following bench test:
CREATE TABLE Foo
(
FooId INT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE Bar
(
BarId INT AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
CREATE TRIGGER FooTrigger AFTER INSERT ON Foo
FOR EACH ROW BEGIN
INSERT INTO Bar () VALUES ();
END;
INSERT INTO Foo () VALUES (); SELECT LAST_INSERT_ID();
This returns:
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
So it uses the LAST_INSERT_ID() of the original table and not the table INSERTed into inside the trigger.
Edit: I realized after all this time that the result of the SELECT LAST_INSERT_ID() shown in my answer was wrong, although the conclusion at the end was correct. I've updated the result to be the correct value.
open MySql command type SELECT LAST_INSERT_ID(); then ENTER
Related
Is it possible to insert a row and get the values inserted in the same query?
Something like...
INSERT INTO `items` (`item`, `number`, `state`)
(SELECT '3', `number`, `state` FROM `item_bug` WHERE `id`='3')
And then, get ID and execute a
SELECT * FROM `items` WHERE `id`='$id'
But using only one query.
Execute your insert statement and then you can do this:
SELECT * FROM `items` WHERE `id`= LAST_INSERT_ID()
you can call a stored procedure which will perform the insert and return a resultset in a single call from your app layer to mysql:
Stored procedure call
mysql> call insert_user('bar');
+---------+----------+
| user_id | username |
+---------+----------+
| 1 | bar |
+---------+----------+
1 row in set (0.02 sec)
$sqlCmd = sprintf("call insert_user('%s')", ...);
Simple example:
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 procedure if exists insert_user;
delimiter #
create procedure insert_user
(
in p_username varchar(32)
)
begin
declare v_user_id int unsigned default 0;
insert into users (username) values (p_username);
set v_user_id = last_insert_id();
-- do more stuff with v_user_id e.g. logs etc...
select * from users where user_id = v_user_id;
end#
delimiter ;
call insert_user('bar');
No, it's not possible in MySQL (unlike PostgreSQL, SQL Server and PL/SQL in Oracle).
You will have to do it in separate queries.
You can do this using multiple statements if you like to choose that route. Firstly when you connect to your database make sure that multiple statements is set to true:
var connection = mysql.createConnection({
host: databaseHost,
user: databaseUser,
password: databasePassword,
database: databaseName,
multipleStatements: true
});
Then you can just define your sql as:
var sql = "your insert statement; your select statement";
Just separate individual statements using the semi colon. Your select result will be results[1] in this example.
if you are using php then
instead of this you can use
mysql_insert_id();
which will give the id of last inserted record.
The other data will be same as inserted.
Only id will change which you can get by mysql_insert_id()
So you do not need to run second query.
After reading this question, I'm trying to convert some SQL from MySQL to PostgreSQL. Thus I need variable assignation:
INSERT INTO main_categorie (description) VALUES ('Verbe normal');
SET #PRONOMINAL := SELECT LAST_INSERT_ID();
INSERT INTO main_mot (txt,im,date_c,date_v_d,date_l)
VALUES ('je m''abaisse',1,NOW(),NOW(),NOW());
SET #verbe_149 = SELECT LAST_INSERT_ID();
INSERT INTO main_motcategorie (mot_id,categorie_id) VALUES (#verbe_149,#PRONOMINAL);
How would you do this with PostgreSQL? No useful sample in the documentation of v9 and v8 (almost the same).
NB: I dont want to use a stored procedure like here, I just want "raw sql" so I can inject it through CLI interface.
There are no variables in Postgres SQL (you can use variables only in procedural languages).
Use RETURNING in WITH query:
WITH insert_cat AS (
INSERT INTO main_categorie (description)
VALUES ('Verbe normal')
RETURNING id
),
insert_mot AS (
INSERT INTO main_mot (txt,im,date_c,date_v_d,date_l)
VALUES ('je m''abaisse',1,NOW(),NOW(),NOW())
RETURNING id
)
INSERT INTO main_motcategorie (mot_id,categorie_id)
SELECT m.id, c.id
FROM insert_mot m, insert_cat c;
As an alternative, you can use custom configuration parameters in the way described in this post.
Create two functions:
create or replace function set_var (name text, value text)
returns void language plpgsql as $$
begin
execute format('set mysql.%s to %s', name, value);
end $$;
create or replace function get_var (name text)
returns text language plpgsql as $$
declare
rslt text;
begin
execute format('select current_setting(''mysql.%s'')', name) into rslt;
return rslt;
end $$;
With the functions you can simulate variables, like in the example:
INSERT INTO main_categorie (description)
VALUES ('Verbe normal');
SELECT set_var('PRONOMINAL', (SELECT currval('main_categorie_id_seq')::text));
INSERT INTO main_mot (txt,im,date_c,date_v_d,date_l)
VALUES ('je m''abaisse',1,NOW(),NOW(),NOW());
SELECT set_var('verbe_149', (SELECT currval('main_mot_id_seq')::text));
INSERT INTO main_motcategorie (mot_id,categorie_id)
SELECT get_var('verbe_149')::int, get_var('PRONOMINAL')::int;
This is certainly not an example of good code.
Particularly the necessity of casting is troublesome.
However, the conversion can be done semi-automatically.
You can run PostgreSQL scripts outside of a function using the do construct. Here's an example with Donald Ducks' nephews. First the nephew will be added to the nephew table, and then we'll add a baseball cap using the newly inserted nephew's id.
First, create two tables for nephews and baseball caps:
drop table if exists nephew;
drop table if exists cap;
create table nephew (id serial primary key, name text);
create table cap (id serial, nephewid bigint, color text);
Now add the first nephew:
do $$declare
newid bigint;
begin
insert into nephew (name) values ('Huey') returning id into newid;
insert into cap (nephewid, color) values (newid, 'Red');
end$$;
The returning ... into ... does in Postgres what currval does in MySQL. Huey's new id is assigned to the newid variable, and then used to insert a new row into the cap table. You can run this script just like any other SQL statement. Continue with Dewey and Louie:
do $$declare
newid bigint;
begin
insert into nephew (name) values ('Dewey') returning id into newid;
insert into nephew (name) values ('Louie') returning id into newid;
insert into cap (nephewid, color) values (newid, 'Green');
end$$;
And you end up with:
# select * from nephew;
id | name
----+-------
1 | Huey
2 | Dewey
3 | Louie
(3 rows)
# select * from cap;
id | nephewid | color
----+----------+-------
1 | 1 | Red
2 | 3 | Green
(2 rows)
See it working at SQL Fiddle.
Is it possible to insert a row and get the values inserted in the same query?
Something like...
INSERT INTO `items` (`item`, `number`, `state`)
(SELECT '3', `number`, `state` FROM `item_bug` WHERE `id`='3')
And then, get ID and execute a
SELECT * FROM `items` WHERE `id`='$id'
But using only one query.
Execute your insert statement and then you can do this:
SELECT * FROM `items` WHERE `id`= LAST_INSERT_ID()
you can call a stored procedure which will perform the insert and return a resultset in a single call from your app layer to mysql:
Stored procedure call
mysql> call insert_user('bar');
+---------+----------+
| user_id | username |
+---------+----------+
| 1 | bar |
+---------+----------+
1 row in set (0.02 sec)
$sqlCmd = sprintf("call insert_user('%s')", ...);
Simple example:
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 procedure if exists insert_user;
delimiter #
create procedure insert_user
(
in p_username varchar(32)
)
begin
declare v_user_id int unsigned default 0;
insert into users (username) values (p_username);
set v_user_id = last_insert_id();
-- do more stuff with v_user_id e.g. logs etc...
select * from users where user_id = v_user_id;
end#
delimiter ;
call insert_user('bar');
No, it's not possible in MySQL (unlike PostgreSQL, SQL Server and PL/SQL in Oracle).
You will have to do it in separate queries.
You can do this using multiple statements if you like to choose that route. Firstly when you connect to your database make sure that multiple statements is set to true:
var connection = mysql.createConnection({
host: databaseHost,
user: databaseUser,
password: databasePassword,
database: databaseName,
multipleStatements: true
});
Then you can just define your sql as:
var sql = "your insert statement; your select statement";
Just separate individual statements using the semi colon. Your select result will be results[1] in this example.
if you are using php then
instead of this you can use
mysql_insert_id();
which will give the id of last inserted record.
The other data will be same as inserted.
Only id will change which you can get by mysql_insert_id()
So you do not need to run second query.
Is it possible to insert a row and get the values inserted in the same query?
Something like...
INSERT INTO `items` (`item`, `number`, `state`)
(SELECT '3', `number`, `state` FROM `item_bug` WHERE `id`='3')
And then, get ID and execute a
SELECT * FROM `items` WHERE `id`='$id'
But using only one query.
Execute your insert statement and then you can do this:
SELECT * FROM `items` WHERE `id`= LAST_INSERT_ID()
you can call a stored procedure which will perform the insert and return a resultset in a single call from your app layer to mysql:
Stored procedure call
mysql> call insert_user('bar');
+---------+----------+
| user_id | username |
+---------+----------+
| 1 | bar |
+---------+----------+
1 row in set (0.02 sec)
$sqlCmd = sprintf("call insert_user('%s')", ...);
Simple example:
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 procedure if exists insert_user;
delimiter #
create procedure insert_user
(
in p_username varchar(32)
)
begin
declare v_user_id int unsigned default 0;
insert into users (username) values (p_username);
set v_user_id = last_insert_id();
-- do more stuff with v_user_id e.g. logs etc...
select * from users where user_id = v_user_id;
end#
delimiter ;
call insert_user('bar');
No, it's not possible in MySQL (unlike PostgreSQL, SQL Server and PL/SQL in Oracle).
You will have to do it in separate queries.
You can do this using multiple statements if you like to choose that route. Firstly when you connect to your database make sure that multiple statements is set to true:
var connection = mysql.createConnection({
host: databaseHost,
user: databaseUser,
password: databasePassword,
database: databaseName,
multipleStatements: true
});
Then you can just define your sql as:
var sql = "your insert statement; your select statement";
Just separate individual statements using the semi colon. Your select result will be results[1] in this example.
if you are using php then
instead of this you can use
mysql_insert_id();
which will give the id of last inserted record.
The other data will be same as inserted.
Only id will change which you can get by mysql_insert_id()
So you do not need to run second query.
What is the equivalent of SQLServer function SCOPE_IDENTITY() in mySQL?
This is what you are looking for:
LAST_INSERT_ID()
In response to the OP's comment, I created the following bench test:
CREATE TABLE Foo
(
FooId INT AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE Bar
(
BarId INT AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
INSERT INTO Bar () VALUES ();
CREATE TRIGGER FooTrigger AFTER INSERT ON Foo
FOR EACH ROW BEGIN
INSERT INTO Bar () VALUES ();
END;
INSERT INTO Foo () VALUES (); SELECT LAST_INSERT_ID();
This returns:
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1 |
+------------------+
So it uses the LAST_INSERT_ID() of the original table and not the table INSERTed into inside the trigger.
Edit: I realized after all this time that the result of the SELECT LAST_INSERT_ID() shown in my answer was wrong, although the conclusion at the end was correct. I've updated the result to be the correct value.
open MySql command type SELECT LAST_INSERT_ID(); then ENTER