I'm a fairly new yii user, and I have a little project I'm doing. I'm not using Yii's model generator since my queries are pretty custom and I'm still not quite at home with the whole yii active record thing, so I'm sticking to the query builder for now. I've grasped the basic ideas of making sql statements, but I think I'm going to run into a problem with one I need to do.
Basically, I'm inserting data into one table, and I need to get the value of the id column of the just inserted data. The easiest way would be to just do an insert and get the max value of the id column, but I'm pretty sure that's not the correct way to do it - since someone else can insert stuff "at the same time" and I might end up getting the wrong value - and I need the right one because I will be inserting it into another table.
I've seen that the return value of the insert() function is an integer, the number of inserted rows so I can't use that.
Basically, is there a way to get the data I just inserted to a table that's 100% correct & safe - even if someone else inserted something to the table "at the same time"?
You want getLastInsertId() of the CDbConnection class:
$id = Yii::app()->db->getLastInsertId();
if you have saved the model, you can access it with
$model->id
assuming that id is the auto increment id field in your database.
obviously, before the model is saved you can't get it's id
Related
I've been struggling with this problem for a while now and can't figure out reasonable explanation for this behaviour...
I have in MySQL a table called "notifications" and columns "package_id", "mail_sent_at" and "sms_sent_at", and appropriate Propel model for that.
I'm setting "sms_sent_at" column with current time and saving it. Works perfectly.
$not = new Notification();
$not->setPackageId($package_id);
$not->setSmsSendedAt(time())->save();
The result for this is:
Now I want to add one more thing - set mail_sent_at column. So what I do:
$not = new Notification();
$not->setPackageId($package_id1);
$not->setMailSendedAt(time())->save();
$not->setSmsSendedAt(time())->save();
And here's the magic: only mail_sent_at column was set.
Additional notes:
after var_dump'ing i can see that dumped object has both properties set after executing these operations
var_dump'ing object retrieved from propel query by package_id after these operations executed doesn't have the second column set. As it is in DB.
Same behaviour happens other way around if I first set different column - first saved column goes into DB, second don't.
Why is that happening and how can I fix it?
Ps. Yeah, I know it's "sent", not "sended"
EDIT
Finally I found the solution. In case someone is having similar problem:
check if your primary key in propel schema has autoIncrement="true". If not - add it!
What was happening was: I've created a new object with id=null, saved it to DB using implicitly SQL INSERT (since it's new record ) and while working on the same object modified it and saved it to DB once again, but this time imlpicitly by SQL UPDATE (Propel figures out that I inserted this object once). The problem was, that after first saving I didn't get id for my object set (even though there was ID set in DB). So second SQL contained "UPDATE...WHERE id = NULL".
I have an in-house PHP class that I use for Object Relational Mapping. I would like to add an improvement to it though, and I'm not sure how to go about it:
When a new record is created, it has a flag marking it as such. When the record is saved, it checks for that flag; if the flag is set, then any fields that were flagged as "auto_increment", are assigned the mysqli::insert_id value.
What I'd like to do is update this so that ~any~ field that the database updates on the save (e.g. TIMESTAMP DEFAULT NOW()), gets assigned back to the object.
So, the only way that comes to mind is as follows:
Save the record
Grab the auto-increment field if applicable
Reload the record with another SELECT
I guess that would work, but it seems a bit roundabout to me. It also depends on none of the key fields being automatically assigned.
Is there any way to get auto-assigned values other than insert_id from the mysqli object after saving the record?
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).
I'm trying to add a row to a table, and then immediately get its unique ID, which is simply an autoincremented column.
Googling tells me PHP can do this through the mysql_insert_id() method, which
Retrieves the ID generated for an AUTO_INCREMENT column by the previous query (usually INSERT).
Is the "previous query" limited in scope to this specific connection, or is it possible that if somehow another row is inserted before I call it, it will return the wrong ID?
Are there any better suggestions on how to get or set a unique ID for a row? I'd make the unique ID on the client-side, but there are multiple clients, so that's not really possible.
Thanks.
Yes, it's limited to connection, so it will return a reliable value.
Try to use mysqli-functions or PDO, MySQL will be deceprated.
I was wondering how can I select a value from a database that a user just entered it into and then add it to another mysql table all in the same script before the script is finished running.
You're probably looking for an insert ... select statement.
If you're talking about adding a value that a user just entered into a form, to something, and then putting that into the database, you should do the addition while in PHP. There's no point in going to the database after you've just inserted the value for this purpose.
If I'm misunderstanding something, please elaborate your question and let us know WHY you would want to figure out a just-inserted database value and do an operation on it, rather than trying to do it before you insert in the first place.
Also, if it's a fairly simple modification consider using an UPDATE statement, not a select --> insert.
Like nash said, you perform a select.
But to get the data from the row that the user just entered, you'll need:
mysql_insert_id()
Which grabs the last ID inserted (this is assuming you have an increment id column)
So assuming just entered his first and last name in a form, you'd insert his first and last name in the database(which i assume you know how since the title of this question is "SELECT a value from MySQL database"), you can get what he just entered by:
$last_id = mysql_insert_id();
If there are no rows on that table yet, then this will return 1. $last_id is now 1 (one).
To select:
SELECT * FROM users WHERE userID = "$last_id"
this will grab what the user just inserted....however, this seems pointless as you can use the variables from the form he just filled
enter code here
In the PHP MySQL module, you normally perform a mysql_select_db() to switch database.
You can insert your data into tables in different databases by switching between them with that function.
However, you can insert data into any table of any database (which the user has access to) by prefixing the database name to the table like so:
INSERT INTO test_db.test_table (`column1`,`column2`) VALUES ('abc',123);
You can use that also to insert data from one table into another using:
INSERT INTO `db1`.`myTable` (`column1`,`column2`) SELECT `column1`,`column2` FROM `db2`.`myTable` WHERE `id`= 5
The WHERE id part should obviously match the id of a row in db2.myTable
If you use doctrine you have the inserted data in the object representing the table and in addition you have primary key assigned for the record inside the object.
Con is doctrine is huge database abstraction layer, so if your application is not big doctrine is hammer for mosquito.
what is the structure of your database? The names of your tables, columns?
Some tutorial that you may want to look at: (grabbed from google)
http://www.phpf1.com/tutorial/php-mysql-tutorial.html
In theory you perform a select, take the data you need and perform an insert.