mysql transaction - mixing insert & select to attain last_insert_id? - php

I'm performing a transaction (using PDO), however I need to grab the insert id of the first element in the transaction, for example:
BEGIN
INSERT INTO user (field1,field2) values (value1,value2)
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
COMMIT;
Then do the pdo stuff:
[...]
$pdo->execute();
$foo = $pdo->lastInsertId(); // This needs to be the id from the FIRST insert
Is there a way to get the last insert id from the first element in a transaction? Perhaps using something like the following:
BEGIN
INSERT INTO user (field1,field2) values (value1,value2)
SELECT id AS user_id FROM user WHERE id=LAST_INSERT_ID()
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
COMMIT;
$pdo->execute();
$fooArray = $pdo->fetchAll();
$lastId = $fooArray[0]['user_id'];
Am I completely out to lunch with ^ ? Is there a better way to do this?
EDIT 1
Based on suggestion, i've updated the query to use variables... however, i don't know how to retrieve the variable values using PDO. Using $stmt->fetchAll() just returns an empty array;
BEGIN
DECLARE User_ID int
DECLARE Option_ID int
INSERT INTO user (field1,field2) values (value1,value2);
set User_ID = select LAST_INSERT_ID();
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
set Option_ID = select LAST_INSERT_ID();
select User_ID, Option_ID
COMMIT;

You can do it this way, put the value into variable then just select it
BEGIN
DECLARE User_ID int
DECLARE Option_ID int
INSERT INTO user (field1,field2) values (value1,value2);
set User_ID = select LAST_INSERT_ID();
INSERT INTO user_option (user_id,field2) values (LAST_INSERT_ID(),value2);
set Option_ID = select LAST_INSERT_ID();
select User_ID, Option_ID
COMMIT;

Related

Need help in MySql query INSERT IF NOT EXISTS Otherwise UPDATE

I need you small help, I would like to update the existing record, If it already exists in table otherwise Insert the new record. I am not using the primary key column in the Where clause.
Every time Its insert the new record in the table with the same column 1 and column 2 values.
I have got the few response as well like use the REPLACE. But REPLACE will work for the case of Unique / Primary Key otherwise inserted the new record.
I have used the below query
Method 1:
IF EXISTS (select * from mytable3 WHERE field1 = 'A') THEN
BEGIN
UPDATE mytable3
SET (field1 ='A', field2 = 'DD')
WHERE field1 = 'A'
END
ELSE
BEGIN
INSERT INTO mytable3 (field1, field2) VALUES ('A', 'DD')
END
Method 2:
REPLACE mytable3 (field1, field2) VALUES ('A', 'DD');
Table structure:
CREATE TABLE mytable3
(
users int(11) NOT NULL AUTO_INCREMENT,
field1 varchar(10),
field2 varchar(10),
PRIMARY KEY(users)
);
insert into mytable3 (field1, field2) values('A', 'AA');
insert into mytable3 (field1, field2) values('B', 'BB');
insert into mytable3 (field1, field2) values('C', 'CC');
Note: every time Its insert the new record in the table with the same field 1 and field 2 values
------------------------- Original Question ------------------
I'm struggling to write MySql query to insert new records if not exists, otherwise Update the existing record. But I am facing the Syntax error as below:
Error Code: 1064. You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'IF EXISTS(SELECT * FROM wnduty.parcel-status-log
WHERE parcel-id = 1 AND `sh' at line 1
The SQl Query as below:
IF EXISTS(SELECT * FROM wnduty.`parcel-status-log` WHERE `parcel-id` = 1 AND `shipping-status-id` = 4)
THEN
BEGIN
UPDATE wnduty.`parcel-status-log` SET (`status-date` ='2016-06-10 10:41:58', `is-synced`= 3)
WHERE `parcel-id` = 1 AND `shipping-status-id` = 4
END
ELSE
BEGIN
INSERT INTO wnduty.`parcel-status-log` (`parcel-id`,`shipping-status-id`, `is-synced`,`status-date`)
values(1, 4, 1, '2016-06-10 10:41:58')
END
END IF
I have also try by below query but still syntax error..
INSERT INTO wnduty.`parcel-status-log` (`parcel-id`, `shipping-status-id`, `is-synced`, `status-date`) values(1, 4, 1, '2016-06-10 10:41:57')
ON DUPLICATE KEY UPDATE
`status-date` ='2016-06-13 11:41:58',`is-synced` = 3, `shipping-status-id` = 4 ;
I am using the MySql version as below:
innodb_version 5.7.12
protocol_version 10
version_compile_os Win64
You can use UPDATE INTO with the same syntax as INSERT INTO and if the record is a duplicate on any of the unique keys in the table then it will update the record, otherwise it will insert using the same SQL statement.
Just use REPLACE instead of INSERT, it does exactly what you are looking for ...
INSERT INTO wnduty.parcel-status-log ...
REPLACE wnduty.parcel-status-log ...
From mysql man :
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 14.2.5, “INSERT Syntax”.
Full REPLACE example :
mysql> CREATE TABLE mytable ( users TINYINT(1), field varchar(10), PRIMARY KEY(users));
mysql> insert into mytable values(1, 'A');
mysql> insert into mytable values(2, 'B');
mysql> insert into mytable values(3, 'C');
Now Replace a row with a new value no matter if it exists or not :
mysql> REPLACE mytable (users, field) VALUES (2, "New Value");
mysql> REPLACE mytable (users, field) VALUES (4, "D");

Use inserted id for another column value

I have an identity column (id) that auto-increments.
id|name|image_path
I want to know if there is some way using mysql, to use the newly inserted id in the image_path.
For example if a new row is inserted and got the id 2 I want the image_path to be "/images/2.png".
Or do I have to use the traditional way, by inserting and then fetching this ID then updating the entry?
My opinion is that it is impossible to do with one query. You won't know new autoincrement value until row will be inserted. Still you can write 1 query to achieve what you want (actually 2 queries would be executed):
insert into `t`(`id`, `name`, `image_path`)
values(
(SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE `table_name` = 't'),
'1234',
concat(
'/images/',
(SELECT `auto_increment` FROM INFORMATION_SCHEMA.TABLES
WHERE `table_name` = 't'),
'.png'
)
)
Anyway much safer would be:
START TRANSACTION;
set #c = (select ifnull(max(`id`),0) + 1 from `t`);
insert into `t`(`id`, `name`, `image_path`) values (#c,'123',concat('/images/',#c,'.png'));
COMMIT;
Yes, it is possible with oracle. We have dynamic sql feature.
have tried the below.
Created a sequence and then created a procedure which takes id as input and creates an insert statement dynamically which will fulfill your requirement.
create sequence seq1 start with 1;
create table image1(id1 number,image varchar2(50));
create or replace procedure image1_insert(id1 in number)
as
sql_stmt varchar2(50);
image_path varchar2(50);
begin
sql_stmt:='insert into image1 values(:1,:2)';
image_path:='/image/'||id1||'.png';
execute immediate sql_stmt using id1,image_path;
end;
begin
image1_insert(seq1.nextval);
end;
id image
4 /image/4.png
5 /image/5.png
select *from image1;

MYSQL - append or insert value into a column depending on whether it's empty or not

As title says, im trying to append a string to a VARCHAR column in my table.
The string is something like " //string ", forward slashes will be used later to explode the string to an array in PHP.
I was wondering if there's a way in MYSQL to perform a CONCAT(columnname, "//string") if the column is empty, otherwise perform a normal UPDATE ... SET ... WHERE . In this way, i will avoid the first value of my future exploded string to be a "//string" with forward slahes.
also, above I 've used bold characters for "in MYSQL" because I know i could first query the DB (to check if the column is empty) with something like:
$q = $conn->dbh->prepare('SELECT columnname FROM tablename WHERE username=:user');
$q->bindParam(':user', $username);
$q->execute();
$check = $q->fetchColumn();
and then leave PHP decide which operation perform:
if ($check != '') { // PERFORM A CONCAT }
else { // PERFORM AN UPDATE }
but this would mean a waste of time/resources due to 2x database calls and more PHP code.
thanks.
https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
That means in your case:
INSERT INTO tablename (id,columnname) VALUES (1,'//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
http://sqlfiddle.com/#!9/bd0f4/1
UPDATE Just to show you your options:
http://sqlfiddle.com/#!9/8e61c/1
INSERT INTO tablename (id, columnname) VALUES (1, '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES (1, '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE columnname='blahblah'), '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE id=2), '//string')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//string');
INSERT INTO tablename (id, columnname) VALUES ((SELECT id FROM tablename t WHERE columnname='newone'), '//newone')
ON DUPLICATE KEY UPDATE columnname=CONCAT(columnname,'//newone');
If what you want is this:
first string: column will contain 'firststring'
second string: column will contain 'firststring//secondstring'
then do the update like this:
UPDATE tablename SET columnname = CONCAT( IF(IFNULL(columnname,'')='','',CONCAT(columnname,'//')), :string) WHERE username=:user

mysql: store a DEFAULT value as a variable

I am wondering how to store the value of a primary key, auto-incremented by "DEFAULT" so that I can insert it as a value in another table row.
So far I have:
$sql = "INSERT INTO sales (
sale_id,
sale_amt,
sale_date)
VALUES (
DEFAULT, # <--- how to store the resulting value of this?
'$amt',
'$date'
)";
I need the specific value created by "DEFAULT" to be stored, so that I can insert it into another table's row. How do I do this with either PHP or MySQL?
You don't. You use last_insert_id() to retrieve it AFTER you've performed the first insert.
INSERT INTO foo (bar) VALUES (baz)
SELECT #id := last_insert_id();
INSERT INTO other (id, parent) VALUES (null, #id)
INSERT INTO yetanother (id, parent) VALUES (null, #id)
Note that last_insert_id() is not smart and will return the id of the LAST insert you did. If you do two inserts, and then try to get the ids, you'll get the id of the second (last) insert.
MySQL:
You can find this in MySQL by using the LAST_INSERT_ID() function, as the last insert ID will be returned that you inserted for an AUTO_INCREMENT value.
$sql = "INSERT INTO sales (
sale_id,
sale_amt,
sale_date)
VALUES (
DEFAULT, # <--- how to store the resulting value of this?
'$amt',
'$date'
)";
sql2 = "INSERT INTO records (
sale_id,
customer_name,
other_info)
VALUES (
LAST_INSERT_ID(), <-------- correct sales_id
'$name',
'$info');

Insert multiple rows with same unique ID

I am inserting multiple rows using one query and, obviously, the ID column auto increments each row. I want to create another ID column and have the ID remain the same for all rows inserted during the query. So if I insert 10 rows during one query, I want all 10 rows to have the id "1". How can this be done? Thanks for any help
If I understood your question correctly, you want to supply an ID for the specific group of INSERT statements.
Assumming you have this schema
CREATE TABLE TableName
(
RecordID INT AUTO_INCREMENT PRIMARY KEY,
OtherColumn VARCHAR(25) NOT NULL,
GroupID INT NOT NULL
)
You can have two statements for this:
1.) Getting the last GroupID and increment it by 1.
SELECT COALESCE(MAX(GroupID), 0) + 1 AS newGroupID FROM TableName
2.) once you have executed it, store the value in a variable. Use this variable for all the insert statement,
$groupID = row['newGroupID'];
$insert1 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('a', $groupID)";
$insert2 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('b', $groupID)";
$insert3 = "INSERT INTO TableName(OtherColumn, GroupID) VALUES ('c', $groupID)";
UPDATE 1
SQLFiddle Demo

Categories