I have this two tables:
I also have a dynamic form in which it contains table and the user can add rows and the data from it will be inserted in tblcamealsformdetails but the basis for inserting it is the id from tblcamealsform. How do I insert all the values to the two tables simultaneously?
Here's my form:
You will enter data first in table tblcamealsform. You insert ID from that query.
That ID you will use then to insert the rest of the data, along with the insert ID, in table tblcamealsformdetails.
So you don't do it simultaniously. You add the dependencies first.
To get the insert-id from the last query you executed, you will need mysql_insert_id().
See http://php.net/manual/en/function.mysql-insert-id.php
In answer to the comment what will happen if multiple users use the form at the same time:
Since you open a mysql connection at the top of your script which will result a unique connection pointer and all of the mysql-functions you call automatically reference to that pointer I think mysql_insert_id() will always reference to the latest query performed by the current connection. So another thread by another user would not interfere with this.
Please note that I am not 100% sure about this though.
Anyway: I am using this for about 10 years now some of which include high-traffic websites and I have never experienced any problems using this method, so in my opinion you can safely use it.
There is one exception to this:
You must always call mysql_insert_id() immediately after executing the query you want the ID for. If you execute any other query in the meantime (for example, you call a method of another object which performs an insert-query) mysql_insert_id() will return the ID of that query instead.
This is mistake I have made in the past and which you have to be aware of.
I'd like to point you using LAST_INSERT_ID:
when doing multiple-row inserts, LAST_INSERT_ID() will return the value of the first row inserted (not the last).
Related
I find this kind of hard to explain, but consider the following situation:
You have a website with two insert queries that get loaded right after eachother, there might be some variable declarations and for loops in between, but no other queries besides these two:
$mysqli->doQuery("INSERT INTO `company_order`(`customer_id`, `item_id`)
VALUES ($givenid, $givenproduct")
// This table has a primary key that gets defined using auto_increment.
/* (loop that defines array with 50~ variables, few names that get defined in object variables) */
$mysqli->doQuery("INSERT INTO `customer_orderlist`(`customer_id`,`order_id`)
VALUES ($givenid, (LAST_INSERT_ID()) ")
Imagine if two users loaded the same function that executes these queries almost right after eachother. Is there a risk that one user might get the last inserted ID from the other user, or is it guaranteed that the queries will be executed in order without any other queries getting called in between them?
The MySQL function LAST_INSERT_ID() returns the first auto-generated value successfully inserted for an AUTO INCREMENT column as a result of the most recent successful INSERT statement executed on the current connection.
The value is stored by the server on a per-connection basis. This guarantees the value returned by LAST_INSERT_ID() on your second query is the value generated for the AUTO INCREMENT column on your first query, no matter how many other INSERT queries run between these two queries on other connections.
To answer your questions:
is it guaranteed that the queries will be executed in order without any other queries getting called in between them?
No, there is no such guarantee. The queries are executed in the order you send them to the server but your connection does not block other connections to execute their own queries (and vice-versa).
Is there a risk that one user might get the last inserted ID from the other user
No. There is no such risk as long as the two queries (the INSERT that auto generates an AUTO INCREMENT value and the query that calls LAST_INSERT_ID()) run on the same connection (and no other INSERT query runs between them on the same connection).
My question is a rather simple one. I've read that the recommended method of retrieving the auto_increment/id value of a row I've inserted in mysqli is the mysqli_insert_id() function. However, I'm not too familiar and had a question: (This is all theoretical at this point)
For these purposes (hence the mysqli bit) this is all going to be from a PHP web application. Say multiple users are on the application at once and another row is inserted from a different page between the time that I insert my row and the time that I call mysqli_insert_id()?
Would that return an incorrect value, or does MySQL have some sort of feature to prevent such a thing? Or am I simply overestimating the possibility of such a scenario?
Thanks for your time.
mysqli_insert_id() is specific to the database connection -- it returns the ID of the row that this script invocation inserted most recently, not any other MySQL client. So there's no conflict if multiple applications are inserting into the database at the same time.
There are two ways in which you can invoke this method:
Object Oriented - $mysqli->insert_id;
Procedural (as you have specified) - mysqli_insert_id(mysqli $link)
In both cases the last insert id relates to the connection you have established with the database. For the purpose of explanation though I believe the Object Oriented approach provides greater clarity. Consider the following code:
$mysqli = new mysqli('host','username','password','database');
// Insert into table with an AUTO INCREMENT field defined`
if ($result = $mysqli->query("INSERT INTO table (somefield) VALUES ('somevalue');")) {
echo 'The ID is: '.$mysqli->insert_id;
}
The $insert_id instance variable is updated whenever the query function is called. Therefore, the value held is only within the scope of your code and not relative to other interactions with the database by some other process.
There are some interesting caveats to consider though. For example, if you decide to do bulk inserts e.g.
$mysqli->query("INSERT INTO table (somefield) VALUES ('somevalue'), ('anothervalue');")
It will return the ID of the first row inserted and not the last.
For further reading PHP Doc provides more clarification.
Consider a simple schema of one to many relationship. Parent Table's Id is referenced in the Child table.
In php I want to insert a row into the table using the statement mysql_query($query). Then I will get the id of the last inserted row by using mysql_insert_id(). Then i will use this id to insert the another row into the child's table.
My question is that the since there could be multiple requests happening on the same time for a php page, what if the above two statements do NOT run one after the other (ie, for example, there are two inserts happening on the parent and then the two inserts on the child)? There could be concurrency issues. So how do we overcome this?
Any ideas?
When you call mysql_insert_id() it gets the last inserted id for that connection, so two PHP scripts won't interfere with each other.
As in MySQL documentation:
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.
So... no problem. Although, for other reasons, I recommend using ORM (like Doctrine).
I am currently working on a PHP project with an Oracle database. To update a table, the php code I'm working with uses a SQL "MERGE INTO" method to loop through a table and see if values for multiple records exist in another table. If they don't exist yet, the values are inserted into my table. If the values already exist, nothing happens.
I would like to have another query run after this that uses the auto incremented id's created in the MERGE INTO query. Is there a way to get an array of the newly created ids? I was hoping for something like mysql_insert_id, but I haven't found anything like that yet.
Thanks!
Oracle has supported the MERGE syntax since 9i. Haven't tried, but you might be able to use the RETURNING clause on the MERGE statement...
Oracle uses sequences for handling automatically incremented values. Once you've created a sequence, you can use:
sequence_name.CURVAL
..to get the current value, like what mysql_insert_id would return. To populate a primary key, you'd use:
sequence_name.NEXTVAL
To populate a primary in an INSERT statement, you'd use:
INSERT INTO your_table
(pk_id, ..
VALUES
(your_sequence.NEXTVAL, ...)
You can use triggers as an alternative, but they won't return the current value.
What auto_incremented ids? AFAIK, There is no such thing in Oracle. You can simulate the behaviour by adding a trigger on the table and a sequence number but there is certainly no equivalent of mysql_insert_id().
I think you need to go back and find another way to identify your records.
C.
I am using adodb for PHP library.
For fetching the id at which the record is inserted I use this function "$db->Insert_ID()"
I want to know if there are multiple and simultaneous inserts into the database table, will this method return me the correct inserted id for each record inserted ?
The reason I am asking this is because I use this last insert id for further processing of other records and making subsequent entries in the related tables.
Is this approach safe enough or am I missing something.
Please help me formulate a proper working plan for this so that I can use the last insert id for further inserts into the other table safely without having to mess up with the existing data.
Thanks
Yes, it's safe for concurent use. That's because LAST_INSERT_ID() is per-connection, as explained here:
The ID that was generated is
maintained in the server on a
per-connection basis. This means that
the value returned by the function to
a given client is the first
AUTO_INCREMENT value generated for
most recent statement affecting an
AUTO_INCREMENT column by that client.
This value cannot be affected by other
clients, even if they generate
AUTO_INCREMENT values of their own.
This behavior ensures that each client
can retrieve its own ID without
concern for the activity of other
clients, and without the need for
locks or transactions.
The $db->Insert_ID() will return you last insert id only so if you are inserting many records and want to get id of each last inserted row, then this will work successfully.
I want to know if there are multiple and simultaneous inserts into the database table, will this method return me the correct inserted id for each record inserted ?
It will return only the most recently inserted id.
In order to get ids for multiple inserts, you will have to call INSERT_ID() after each statement is executed. IE:
INSERT INTO TABLE ....
INSERT_ID()
INSERT INTO TABLE ....
INSERT_ID()
...to get the id value for each insert. If you ran:
INSERT INTO TABLE ....
INSERT INTO TABLE ....
INSERT_ID()
...will only return the id for the last insert statement.
Is this approach safe enough or am I missing something.
It's safer than using SELECT MAX(id) FROM TABLE, which risks returning a value inserted by someone else among other things relating to isolation levels.