get auto increment value for an inserted row safely - php

i have a table in the database contains _id column which is the primary key for this table , actually this column value is set by the auto increment approach , is there any safe way to get the value that the auto increment value given to the row i when i make the insert ??? i saw a solution says :" call mysql_insert_id() immediately after your insert query." is it safe to use( i.e does it get a wrong value if the same script in different thread )??? if not is there any way to make a synchronized block in php?

as far as I know, the id returned from mysql_insert_id is the auto increment id from the last insert query for the current connection (mysql_connect) to the sql database. The only reason for having to call it right after the query is that if you run two insert queries right after each other, mysql_insert_id returns just the last query. It wouldn't be reliably possible to get the id from the first query. Also, it gets the id from the last query, so if you did an insert then update, then ran mysql_insert_id. It would return 0 because the last query (update) isn't an insert.
Also, php just calls the mysql function mysql_insert_id. From the mysql manual:
The value of mysql_insert_id() is affected only by statements issued
within the current client connection. It is not affected by statements
issued by other clients.

If your different threads are each using their own connection to the MySQL server, it should be fine. If not, you'll probably have to use a mutex or semaphore, which should be provided by your threading library.

Yes; $id = mysql_insert_id(); straight after your query.

It's usualy safe to do it, but there maybe be synchronization problems.
What i suggest is to put your sqls into a transaction block :
mysql_query('BEGIN TRANSACTION');
mysql_query('INSERT...');
$x = mysql_insert_id();
mysql_querry('COMMIT');
EDIT: you also may put a write lock on the table until you read the id and then release the lock. But you only need this if you have synchronization problems (same thread)

In PDO, the correct way is to use PDO::lastInsertId()
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDBPDO";
try{
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', 'john#example.com')";
// use exec() because no results are returned
$conn->exec($sql);
$last_id = $conn->lastInsertId();
echo "New record created successfully. Last inserted ID is: " . $last_id;
}catch(PDOException $e){
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
?>

As well You can use single one query to get autoincrement id, like:
INSERT INTO table_name(field_1,field_2) VALUES(:field_1,:field_2) RETURNING id;
or
INSERT INTO table_name (field_1) OUTPUT INSERTED.id VALUES (?);
Both are returning your autoincrement id
Regarding to:
https://www.php.net/manual/en/pdo.lastinsertid.php

Related

SQL insert with joins and values

This question has kinda been asked already but I couldn't find my answer. I searched a while and found these related questions, but they didn't help me to understand or answer my problem.
SQL Insert Into with Inner Join
T-SQL INSERT INTO with LEFT JOIN
My question is how to insert data in 2 tables using joins. For example (with php) a user can enter his/her name and the foods he/she likes.
I store them in a variable and an array (the length of the array is not always 3 like below):
$name = "Niels"
$foodsHeLikes = array("apple", "pear", "banana");
This is how I want to store them:
USERS:
UserID name
1 Niels
FOODS:
FoodID userID name //userID is linked to UserID in users table
1 1 apple
2 1 pear
3 1 banana
The link to the first question I pasted above has an insert with a join but I don't see anywhere to put the values in like with a normal insert?
The query from that question:
INSERT INTO orders (userid, timestamp)
SELECT o.userid, o.timestamp FROM users u INNER JOIN orders o ON o.userid = u.id
Judging by what's been going on in the comment section, what you're asking is that you would like to have a more optimal query process. Right now you are using two different queries to populate your two tables, and you're wondering whether that could be done more optimally.
First things first, it's not possible to populate TWO different tables with ONE query.
However, what you could do, is use transactions.
The rest of this answer will follow the assumption that you are using PHP as your backend scripting language (as you tagged yourself).
Also, it is not inherently obvious whether you use prepared statements for your queries or not. In the case you don't, I would highly recommend using prepared statements. Otherwise, you're opening yourself up to SQL Injections (SQLI Attacks).
I will proceed by using mysqli prepared statements in this answer.
<?php
// Your input post variables
$name = $_POST['name'];
$foodArray = $_POST['foodArray'];
/*
I'm using a function to handle my queries,
simply because it makes large piles of code easier to read.
I now know that every time the function:
createUserAndFood($name, $foodArray);
is called, that it will populate my user and food table.
That way I don't have to worry about writing all the code multiple times.
*/
function createUserAndFood($name, $foodArray){
// food array values
$foodValues = array_values($foodArray);
// DB variables
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if($conn->connect_error){
die("Connection failed: " . $conn->connect_error);
}
/*
Stops the query from auto commiting,
I'll explain later, you can "maybe" disregard this.
*/
$conn->autocommit(FALSE);
// Declare the query
$sql = "INSERT INTO userTable(name) VALUES(?)";
// Prepare and bind
$stmt = $conn->prepare($sql);
$stmt->bind_param("s", $name);
// Execute the query
$stmt->execute();
// Fetch last inserted id
$lastID = $conn->insert_id;
$sql = "INSERT INTO foodTable(userId, food) VALUES(?, ?)";
$stmt = $conn->prepare($sql);
for($i = 0; $length = count($foodValues) > $i; $i++){
$stmt->bind_param("is", $lastID, $food);
$food = $foodValues[$i];
$stmt->execute();
}
// Commits the query / queries
$conn->commit();
// Close connection
$stmt->close();
$conn->close();
}
?>
Since you wanted to optimize your queries, the general idea that we are using here, is that we are making use of the MySQL function LAST_INSERT_ID(); via PHP and store it into a variable.
Now, this is mainly relevant if you are using auto incremented id's. If you are not, you can disregard this specific logic and use something else. But if you are, then keep reading.
The reason why we are storing the last id into a variable is because we need to use it multiple times (the new user might have more than one favorite food afterall). If you were not to store the last id into a variable, it would instead take the auto incremented value of the second table after the initial insert, which means upon your third insert statement and forward, you would be working with the wrong id.
Now, as I promised to explain, the reason I'm using $conn->autocommit(FALSE); and $conn->commit(); is because you might not want incomplete data sets in your database. Imagine that a user input is happening, but your database crashes in the middle of it all. You'll have incomplete data sets. If this is not really a concern of yours, then you can disregard that.
To simplify what's going on at the MySQL side of things, think of it like this:
BEGIN;
INSERT userTable SET name = '$name';
SET #lastID = LAST_INSERT_ID();
INSERT foodTable SET id = #lastID, food = '$food';
COMMIT;

php mysql get id of last insert row giving error

i want to get the id of last inserted row and i m using mysql_insert_id() function. but giving issue
here is my code :
if($i == 0)
{
$query = "update events set e_did ='".$multi_event."' where eid = '".$display_id."'";
mysqli_query($con,$query);
file_put_contents('log.txt', mysql_insert_id(), FILE_APPEND);
}
else
{
$query = "INSERT INTO events (start_date, end_date, text, rec_type, event_pid, event_length, e_did) VALUES ('".$row['start_date']."','".$row['end_date']."','".$row['text']."','".$row['rec_type']."','".$row['event_pid']."','".$row['event_length']."','".$multi_event."')";
mysqli_query($con,$query);
file_put_contents('log.txt', 'A'.mysql_insert_id().'A', FILE_APPEND);
}
now both time i m getting same id. what is the issue. is i m doing wrong something somewhere ?
If you use the mysqli functions, you must use mysqli_insert_id. You can't mix ext/mysql and ext/mysqli.
Also, UPDATE does not generate a new auto-increment id. You should call mysqli_insert_id() after INSERT, but not UPDATE.
mysqli_insert_id() only returns an id for INSERT queries. An update query will NOT return an id, because by definition you must already have a row in the database for it be getting updated.
With UPDATE, you are editing records, not adding ones. So no new IDs are generated. You can only use mysql_insert_id on INSERT.
Note: mysql_* functions are deprecated and won't be supported in future versions. You should be using either mysqli_* or PDO.

MYSQL: SQL query to get the value of autoincrement field

I have a table. The primary key is id and its auto incremented.
Now when I insert a new record, I need to get the id with which the record was updated.
How can I do that? If i use the query...
select max(id) from table_name
...after executing I can get the id. But can I be sure that its the id of the record that was just inserted? Because many people will be using the app at same time.
I am using php and mysql.
Can ayone provie me a sample code snippet in php with mysql?
If you want to find out what the newest ID from an auto increment column is, you just have to run the mysql_insert_id() function right after your insert query.
Like so:
//--connection already made to database
//--now run your INSERT query on the table
mysql_query("INSERT INTO table_name (foo_column) VALUES ('everlong')");
//-- right after that previous query, you run this
$newest_id = mysql_insert_id();
And now $newest_id will contain the ID of the latest row inserted.
Assuming you're using the MySQLi PHP extension, the command you want is mysqli_insert_id
In SQL you can do this
SELECT LAST_INSERT_ID()
In php you can call mysql_insert_id()
Using the same connection, run this query next:
SELECT LAST_INSERT_ID()
Your database driver may have a convenience function for that.
Read the docs.
you can use this to get the value of the next auto_increment value (given that you already connected to the server and selected the db;
$query = "SHOW TABLE STATUS LIKE 'tbl_name'";
$result = mysql_query($query);
$auto_incr_val = mysql_result($result, 0, 'Auto_increment');
echo $auto_incr_val;
This will give you the value that will be used next in the auto_increment column.
EDIT: I'm sorry.. That wasn't your question....
Here is example in PHP:
$link = mysql_connect('localhost', 'mysql_user', 'mysql_password');
if (!$link) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db('mydb');
mysql_query("YOUR QUERY HERE", $link);
$inserted_id = mysql_insert_id($link));
Query
show create table
contains information you need in last string

php mysql_insert_id(); not working

Hi guys I was hoping from some help here, please.
I have a INSERT query to a table, after this is done I am calling:
mysql_insert_id();
In order to send the last ID inserted into the table to the next page like this:
$insertGoTo = "confirm_booking.php?booking_ID=" .$_POST['booking_ID']. "";
Unfortunately it does not work, all I get is a zero.
The table I am inserting into has an auto increment number and values are inserted into it.
I have also tried SELECT MAX(id) FROM mytable. This dosn't work neither.
I know that this problem has been talked about already. I read all posts but nothing came useful.
Many thanks Francesco
You have to use the value returned by MySql_Insert_Id () when you generate your link:
// your query
$newId = MySql_Insert_Id ();
$insertGoTo = "confirm_booking.php?booking_ID=" . $newId;
It is possible that your table does not have any AUTO_INCREMENT field!
It could also happen because you have two or more mysql connections at the same time.
In this case you should use a link identifier.
$link = mysql_connect( ... );
mysql_select_db('mydb', $link);
mysql_query('INSERT mytable SET abc="123"', $link);
$inserted_id = mysql_insert_id($link);
Some key points from the PHP Manual:
The ID generated for an AUTO_INCREMENT
column by the previous query on
success, 0 if the previous query does
not generate an AUTO_INCREMENT value,
or FALSE if no MySQL connection was
established.
If not having an AUTO_INCREMENT field is not your problem, you might want to try storing the result of the mysql_query call and using that as an argument to the id function
$result = mysql_query("...");
$id = mysql_insert_id($result);
Had an issue using a query like this:
INSERT INTO members (username,password,email) VALUES (...)
reason being that the id (which is my primary key and Auto Increment field) is not part of the query.
Changing it to:
INSERT INTO members (id,username,password,email) VALUES ('',...)
using a an empty value '' will have MySQL use the Auto Increment value but also allow you to use it in your query so you can return the insert id
mysql_insert_id may return 0 or false if your insert fails right?
So if you have trouble with mysql_insert_id not retunring what you expect confirm that you don't have a unique constraint or some other problem with your sql that would cause the insert to fail. Using max is a terrible idea if you consider this.
Make sure to put mysql_insert_id()after the
mysql_query($sql, $con); //Execute the query
Above query responsible for execute your Insert INTO ... command.
After you can get the last ID inserted
I have also suffer from this problem. Finally I found that the problem occur in my connection to the database. You can use this following connection code to connect the database then you can easily use mysqli_insert_id().
$db_connect = mysqli_connect("localhost", "root", "", "social");
Then you can use mysqli_insert_id() as
$id = mysqli_insert_id($db_conx);
I hope this will help you. I you have any problem then leave your comment.
The mysqli_insert_id function has been deprecated. This may be your problem.
Instead, try $mysqli->insert_id. See the documentation for more info.

My SQL triggers

Is it possible to set up a mysql trigger that fires back the id number of that record when ever there is an insert into the database AND how do i capture that using php?
Unless I don't fully understand your question, you don't need a trigger for this - just use the "last inserted ID" functionality of your database driver.
Here's an example using the basic mysql driver in PHP.
<?php
$db = mysql_connect( 'localhost', 'user', 'pass' );
$result = mysql_query( "insert into table (col1, col2) values ('foo', 'bar')", $db );
$lastId = mysql_insert_id();
This is a connection-safe way to obtain the ID.
As explained in the previous answers, you'd don't need to use a trigger to return the identity. You can use the mysql_insert_id() command as described in the [documentation][1].
However if you need to use the new insert id in a trigger, use NEW.[identity_column_name] as follows:
CREATE TABLE temp (
temp_id int auto_increment,
value varchar(10),
PRIMARY_KEY(temp_id)
);
CREATE TRIGGER after_insert_temp AFTER INSERT ON temp
FOR EACH ROW
BEGIN
DECLARE #identity;
SET #identity = NEW.temp_id;
-- do something with #identity
END
I'm not really sure what you're asking. Are you wanting to insert a row into the database and get the id it was assigned too? If so do this
printf("Last inserted record has id %d\n", mysql_insert_id());
You do not need a trigger to accomplish what you are trying to do.
Simply calling PHP's mysql_insert_id will return the ID generated from the last INSERT query executed.
Described here:
http://us2.php.net/manual/en/function.mysql-insert-id.php

Categories