SQL - INSERT and catch the id auto-increment value - php

What is the best way to get the auto-id value in the same SQL with a SELECT?
A forum said adding this "; has Return Scope_Identity()"
in the end of the SQL works in ASP.
Is there a corresponding way in PHP?

It depends on your database server. Using MySQL, call mysql_insert_id() immediately after your insert query. Using PostgreSQL, first query "select nextval(seq)" on the sequence and include the key in your insert query.
Querying for "select max(id) + 1 from tbl" could fail if another request inserts a record simultaneously.

In postgres the best way is to do something like:
insert into foos(name) values ('my_foo') returning id;

It depends on the database engine you are using. Some DBMS, like Firebird for example, have RETURNING clause you can add to your query. For example, if you have a table named TABLE1 with autoincrement column named ID, you can use this:
insert into TABLE1(columns...) values (values...) returning ID;
And it would return the inserted ID just like a regular select statement.

In Microsoft Transact SQL you can use ##IDENTITY.
e.g.
DECLARE #Table TABLE ( col0 INT IDENTITY, col1 VARCHAR(255), col2 VARCHAR(255))
INSERT INTO #Table (col1, col2) VALUES ('Hello','World!')
SELECT ##Identity
SELECT * FROM #Table

In php: mysql_insert_id()
http://us3.php.net/mysql_insert_id
or
If you wanted to genterate the number from your mySql select query, you could use this
EDIT:
SELECT LAST_INSERT_ID(`1`) + 1 FROM table

Be very careful: Apparently select nextval(seq) does not work in high concurrency - some other connection can insert between the time when you inserted and the time when you called select nextval(seq). Always test such code in high concurrency test harnesses.

In SQL Server a insert using the select statement can have an output clause which will return the identity value and whatever other columns you might need to identify which identity goes to which record. If you are using a values clause, then use select scope_identity () immediately after the insert.

Related

Common syntax in MySQL and MSSQL for IF INSERT ELSE UPDATE

I have a PHP 7.3 project which connects via PDO to a MySQL database or a MSSQL database, depending on being run on Linux or Windows.
I want to insert a new values into a table, if the unique value is not yet in that table. If it is already in the table, I want to update the non-unique values.
I searched a lot of docs and SO posts, also, but I couldn't find a syntax, which does that in one query for both database types.
SQL Server query:
IF (EXISTS (SELECT * FROM failed_logins_ip_address WHERE ip_address = 'xxx'))
BEGIN
UPDATE failed_logins_ip_address
SET attempts_count = attempts_count + 1, attempt_datetime = CURRENT_TIMESTAMP
WHERE ip_address = 'xxx'
END
ELSE
BEGIN
INSERT INTO failed_logins_ip_address (ip_address, attempts_count, attempt_datetime)
VALUES ('xxx', 1, CURRENT_TIMESTAMP)
END
MySQL query:
INSERT INTO failed_logins_ip_address (ip_address, attempts_count, attempt_datetime)
VALUES ('xxx', 1, CURRENT_TIMESTAMP)
ON DUPLICATE KEY
UPDATE attempts_count = attempts_count + 1, attempt_datetime = CURRENT_TIMESTAMP
'ip_addess' column is unique, and the table structure is identical for both MSSQL and MySQL.
Is there a syntax, which can do an IF INSERT ELSE UPDATE in both database types?
Yes, I do (PDO) parameter binding, xxx is just to shorten the code snippet.
Yes, I could use identical syntax if I did it in two queries (first select, then insert or update) but I want to avoid (hopefully) unnecessary queries.
No, I do not want to insert every login attempt so I do not need the update anymore because I do not need this data.
If the REPLACE approach would work: this does not update, it deletes and inserts, which I also do not want.
My current solution: I check in PHP for the current database type and switch/case the query strings. It is clean but one string is even less smelly ;-)
UPDATE:
I changed the MSSQL query around: from of IF NOT EXISTS TO IF EXISTS to improve the efficiency. UPDATE will occur a lot more often than INSERT, so in most of the cases, only the first (sub)query will be executed.
After digging deeper, I found this post by a Derek Dieter, which describes how to replace SQL Server's IF EXISTS ELSE by WHERE EXISTS:
https://sqlserverplanet.com/optimization/avoiding-if-else-by-using-where-exists
The WHERE EXISTS syntax seems to be the same in MySQL and MSSQL.
Derek Dieter's example, with IF EXSISTS:
IF NOT EXISTS (SELECT 1 FROM customer_totals WHERE cust_id = #cust_id)
BEGIN
INSERT INTO customer_totals
(
cust_id,
order_amt
)
SELECT
cust_id = #cust_id
,order_amt = #order_amt
END
ELSE
UPDATE customer
SET order_amt = order_amt + #order_amt
WHERE cust_id = #cust_id
END
Derek Dieter's example, with WHERE EXISTS:
INSERT INTO customer_totals
(
cust_id,
order_amt
)
SELECT TOP 1 — important since we’re not constraining any records
cust_id = #cust_id
,order_amt = #order_amt
FROM customer_totals ct
WHERE NOT EXISTS — this replaces the if statement
(
SELECT 1
FROM customer_totals
WHERE cust_id = #cust_id
)
SET #rowcount = ##ROWCOUNT — return back the rows that got inserted
UPDATE customer
SET order_amt = order_amt + #order_amt
WHERE #rowcount = 0
AND cust_id = #cust_id — if no rows were inserted, the cust_id must exist, so update
I still have to test it, though, in MySQL. I'll update this post and add the code, if it works.
If you are using PHP, then you are calling the code through an interface. You can do the following:
Create a unique index on ip_address.
Attempt to insert a new row. This will fail if the row already exists.
If the insert fails (particularly with a duplicate key error), then update the existing row.
However, your goal of trying to have the same code in both databases is . . . just not going to work very well. The two databases are rather different. Perhaps you should consider constructing stored procedures in each database to do what you want and then calling those stored procedures.

Is it possible to insert data in two different table using single mysql query without transaction?

I know this is possible using transaction but I want to do it using single mysql query.
this is which common format transaction
START TRANSACTION;
SELECT #A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=#A WHERE type=1;
COMMIT;
but I need to know a single mysql query is possible?
Normally, you can not do this in MySQL. But you can do this using concat query.
INSERT INTO your_table
(value1,value2,value3)
VALUES
(a,b,c),
(d,e,f),
(i,j,k);
But this is not your question answer. so Your question answer is NO. MYSQL is not support it still now.
No, it can't be done in single statement like
insert into table1,table2
either you do separately like
insert into table1 ...
insert into table2 ...
(OR)
Wrap the insert statements in stored procedure and call that procedure like
create procedure sp_insert_multiple
as
begin
insert into table1 ...
insert into table2 ...
end
Call the SP
exec sp_insert_multiple
You can't do this. However, you can use a transaction and have both of them be contained within one transaction.
START TRANSACTION;
INSERT INTO table_1 VALUES ('1','2','3');
INSERT INTO table_2 VALUES ('one','two','three');
COMMIT;
See the following rule
Normally it is not possible to insert multiple table in single query. you can insert multiple row in a single table . like as
INSERT INTO tbl_test
(a1,a2,a3)
VALUES
(1,2,3),
(4,5,6),
(7,8,9);
you can do this in Oracle
by using procedure you can insert
create procedure insert_query
as
begin
insert into tbl_test1(a1,a2,a3) VALUES (1,2,3)
insert into tbl_test2 (b1,b2,b3) VALUES (1,2,3)
end
you can do that like coz
MySQL doesn't support multi-table insertion in a single INSERT statement.
INSERT INTO NAMES VALUES(...)
INSERT INTO PHONES VALUES(...)
here is a link of detail answer..
sql - insert into multiple tables in one query

mysql is it possible to do insert into insert?

what am doing is clonning an old database to new one with different structure but should have same old data
is it possible to do an insert into insert that return id of the insert query
INSERT INTO tab1 (nom,id_2) VALUES
("jack",(INSERT INTO tab2 (pass) VALUES ("1234")));
in INSERT INTO tab2 (pass) VALUES ("1234") i want to get the id of the insert
but no luck!! (i want it in one sql query (i already know about mysql_insert_id) )
thanks in advance
You cant do this on a single query - use mysql_insert_id() to get the last inserted id for example :
mysql_query('INSERT INTO tab2 (pass) VALUES ("1234")');
$lastid = mysql_insert_id();
mysql_query('INSERT INTO tab1 (nom,id_2) VALUES ("jack",'.$lastid.')');
insert id can be retrieved in mysql as well, so here is a version with no PHP involved (it however performs 2 queries)
INSERT INTO tab2 (pass) VALUES ("1234");
INSERT INTO tab1 (nom,id_2) VALUES("jack",LAST_INSERT_ID());
Lock the table, insert, select max(id), unlock table. This is the only way outside creating your own sequence tables like in postgres if you are adverse for some reason to the last insert id functions. This approach however is going to be like pouring tar into a blender if your table is moderate to high writes.
You can't do this as a single insert because inserts are atomic that is, the ID isn't determined until the statement completes.
Wrap both statements in a transaction and you will get your ID, and atomicity.

PHP & Mysqli - Multiple querys in one?

I need to get the ID (a column) from the last row inserted, in a table. I'm wondering if there's any way to somehow embed that in another query, to avoid having two different querys? It seems much simpler, and i believe i've seen it somewhere before.
Something like this:
$query = "INSERT INTO a_table (x, y) VALUES ((SELECT id FROM another_table ORDER BY id DESC), 'y...')";
Any ideas how to do that?
Thanks.
If you're looking to get the newest record created by your script, you should never do it this way in the first place. What if another instance of your script created a record at the same time?
mySQL's LAST_INSERT_ID() will return the last ID created over this specific connection. However, you must call it immediately after your insert statement.
If getting the highest ID is literally what you want, GSto's answer will work for you.
INSERT INTO a_table (x, y) VALUES (SELECT max(id), 'y...' FROM another_table);
Yes, MySQL has an INSERT .. SELECT statement:
example:
INSERT INTO a_table (x,y) SELECT id,'y' FROM another_table ORDER BY id DESC
although keep in mind, unless you have an auto_incrementing ID field, the order by clause is pointless here.

What's the easiest way to duplicate a column?

Currently, I'm getting the ID of the column via a select statement and insert all the returned values (except the ID).
Is there an easier way to do it?
I don't know Oracle one bit, but there should be an equivalent to
INSERT INTO TABLENAME select * FROM tablename WHERE id = x

Categories