The equivalent of SQLServer function SCOPE_IDENTITY() in mySQL? - mysql

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

MySQL; the function value doesn't appear in resulted table

I created a table with three fields and applied a created function to automatic concat two fields of the same record and the result appears in the third field of the table at the same record.
While the problem is whenever I do insert statement the result of the function appears as error but not on the table!!! the following is the code:
create table Tab (
stuId varchar (1),
stuName varchar (10)
recordCon varchar (20),
primary key (stuId));
Auto concat function for one record by input id:
DELIMITER //
CREATE FUNCTION AutoCon (id varchar (1)) RETURNS int DETERMINISTIC
BEGIN
DECLARE name varchar(10);
DECLARE Con varchar(20);
select stuName from Tab where stuId = id into name;
Select concat(id, name) into con;
RETURN con;
END
//
DELIMITER ;
insert into Tab values ('1a', 'Rami', AutoCon('1a'))
the result
a1 Rami null
FUNCTION AutoCon (id varchar (1)), but you pass 2 chars as the parameter - AutoCon('1a')
Something wrong there ...

MYSQL: INSERT + ON DUPLICATE KEY UPDATE + SELECT in *one* prepared statement? [duplicate]

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.

No query result with SCOPE_IDENTITY() [duplicate]

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

PostgreSQL: a valid variable assignation sample?

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.

How to return the value of a column immediately after an INSERT statement? [duplicate]

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.