Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i append an auto increment primary key to another field in the same table?

I'm using yii active records for mysql, and i have a table where there's a field that needs to be appended with the primary key of the same table. The primary key is an auto increment field, hence i can't access the primary key before saving.

$model->append_field = "xyz".$model->id; // nothing is appending
$model->save();
$model->append_field = "xyz".$model->id; //id is now available

How do i do this?
I know that i can update right after insertion, but is there a better method?

like image 425
bool.dev Avatar asked Nov 29 '11 23:11

bool.dev


3 Answers

Your record is only assigned an id after the INSERT statement is executed. There is no way to determine what that id is prior to INSERT, so you would have to execute an UPDATE with the concatenated field value after your INSERT.

You could write a stored procedure or trigger in MySQL to do this for you, so your app executes a single SQL statement to accomplish this. However, you are just moving the logic into MySQL and in the end both an INSERT and UPDATE are occurring.

like image 78
Carl Zulauf Avatar answered Oct 17 '22 10:10

Carl Zulauf


Some more workarounds:

This is almost your approach ;)

$model->save();
$model->append_field = "xyz".$model->id; //id is now available
$model->save();

But you could move this functionality to a behavior with a custom afterSave() method, note that you'd have to take care about not looping the event.

Or just write a getter for it

function getFull_append_field(){
  return $this->append_field.$this->id;  
}

but then you can not use it in a SQL statement, unless you create the attribute there with CONCAT() or something similar.

like image 3
schmunk Avatar answered Oct 17 '22 08:10

schmunk


Anyone else coming to this question might be interested in exactly how i implemented it, so here's the code :

//in the model class
 class SomeModel extends CActiveRecord{
  ...
  protected function afterSave(){
     parent::afterSave();
     if($this->getIsNewRecord()){
        $this->append_field=$this->append_field.$this->id;
        $this->updateByPk($this->id, array('append_field'=>$this->append_field));
     }
  }
 }

One way to avoid the looping the event(as mentioned by @schmunk) was to use saveAttributes(...) inside the afterSave() method, but saveAttributes(...) checks isNewRecord, and inserts a value only if it is a new record, so that requires us to use setNewRecord(false); before calling saveAttributes(...).
I found that saveAttributes(...) actually calls updateByPk(...) so i directly used updateByPk(...) itself.

like image 2
3 revs Avatar answered Oct 17 '22 09:10

3 revs