CakePHP 1.3.0, mysqli
I have a model, Manifest, whose ID should be the unique number from a printed form. However, with Manifest.id set as the primary key, CakePHP is helping me by setting up auto-increment on the field. Is there a way to flag the field via schema.php and/or elsewhere to disable auto-increment? I need just a plain, old primary key without it.
The only other solution I can imagine is adding on a separate manifest number field and changing foreign keys in a half dozen other tables. A bit wasteful and not as intuitive.
I just tested this out on my cake sandbox and it worked.
All you need to do is set the id field in the data you're saving. So, if you're saving post data, and you want the id to be 200 (arbitrary; you could use another table field or user input or anything else for this source).
$this->data['Manifest']['id'] = 200;
Is that what you're after, being able to set your own values for id's rather than auto incrementing them?
You should be able to include the ID field in the add form. Just make sure to override its default type or CakePHP will turn it into a hidden field.
echo $this->Form->input('id', array('type' => 'text'));
I am a bit curious about this. Of course you cannot save a record without the primary key (which is ID in your case) set. So if you don't want the ID to be incremented automatically, then you must be saving your own ID. And it shouldn't cause a problem.
Are you using a mysql database? If so, do you have the auto_increment set to true on the ID field? Then mysql itself will automatically increment the ID whenever you save a record won't it?
You can set your schema in the Manifest model: http://book.cakephp.org/view/442/_schema.
Related
For example: I create new model, set the id field to 1 and save it. It runs fine and saves with the id = 1 into a database. I open MySQL console and delete all records from the table. When I delete it, create new model again and set the id field to 1 - it actually saves it with the 2 as the id field value.
I'm guessing Yii gets the current auto_increment value from mysql and override my id value. Is there a way to prevent that behavior?
EDIT (my code sample):
$sn = new SaplingNode();
$sn->id = 1;
$sn->save();
I call it twice, between calls I delete the record using mysql console. That's all.
There is no way to do this by Yii framework. As its a default behavior of MYSQL.
You can simply do this and reset the Auto increment id after you truncate.
ALTER TABLE tablename AUTO_INCREMENT = 1
This is not a best practice, but if you really want to forcefully set the id of new record on auto increment column, you can do like below:
First under your rules() method of "SaplingNode" model put below line:
array('id', 'safe'),
Then use your code to save new record with whatever id you like, for example:
$sn = new SaplingNode();
$sn->id = 10;
$sn->save();
This code should work, I have tested it.
As you are currently using it, the answer is no, you can't do that, not with CActiveRecord. The reason for this is that Yii is retrieving the record to update based in it's primary key, and will not override that. The only way to override the primary key will be to write your own update query via a CDbCommandBuilder.
BTW: There is an interesting discussion on the subject, on Yii forum.
Have you tried
$sn = new SaplingNode();
$sn->setPrimaryKey(1);
$sn->save();
Yii primary key
If your just testing and it is okay to delete all data from your table, you can empty the table. For example, you can use phpMyAdmin, click your DB to view its tables, find the table you want and click Empty showing on that table row. You will get a confirmation message with a choice of enabling or disabling FK, click OK and all data on that table will be deleted and your auto increment id will start from 1 when saving or inserting new record.
I have web application built on CakePHP 1.2.11. and mysql database. In this application I have two tables, namely, users and actions. Users hasMany actions and the user_id (id in users tables) is the foreign key in actions table. The id field is autoincrement integer.
CakePHP documentation said that setting the id field to be Char(36) will make CakePHP able to generate Unique string for each record to be the id.
My application is running and I don't want to loss the data records that my application already has. I need to know if it is safely possible to migrate from autoincrement integer id to char(36) keeping in mind the related table?
In other word, How could I change integer value to the unique string id that cakephp do? Is there any rules? If there any tool automate this kind of migration, I will be appreciated to know it.
Yes, simply alter the table to use a varchar. An INT column can be translated into a char, so you won't lose the original IDs (you will end up with a mix of both old regular ints and new uuids). You will need to make sure the change is also made to any foreign keys on any other tables that will need to store VARCHAR(36) as well.
Then make sure to push the new code live immediately otherwise the new records will not be able to be created, because a varchar field can't be auto-increment.
Lastly, immediately after pushing the new code, clear your model cache so Cake doesn't still think it's an INT.
Are you sure you want to switch?
Honestly, unless you have a really good reason to change to UUIDs (CHAR(36)), then I would recommend just staying with auto-incrementing IDs. There are plenty of people that tout the benefits of each, but it boils down to auto-incrementing IDs can be faster, and unless you have multiple databases where you're worried about overlapping data, auto-ids are just fine. (And it's not a simple "switch")
Not crazy-simple:
If you still are sure you want to switch to UUIDs, there is no automated process, but be careful - it's not just about switching the field types and voila - you'll have to create a script or something to update the id fields as well as all the associated fields (ie 'user_id' in the 'actions' table won't be updated..etc etc).
If so, here's how:
So - create a duplicate of your database (or tables) as back-up. You'll then probably want to rename the 'id' field to 'autoid', create another id field CHAR(36), run a script to populate all the UUIDs, then another script that populates the associated ids (ie 'user_id' in the 'actions' table) with the corresponding UUID.
CakePHP code that generates UUIDs:
Here's the link to creating a UUID in CakePHP 1.2: http://book.cakephp.org/1.2/en/view/826/uuid
My db table looks like this pic. http://prntscr.com/22z1n
Recently I've created delete.php page. it works properly but when i deleted 21th user next registered user gets 24th id instead of 21.
Is it possible to put newly registered users info to first empty row? (In this situation 21th row)
In my registration form, newly registering user can write names of existing users, and be friends with them after registration. For this friendship i have another table that associates id of newly registered user and existing user.
For this purpose i'm using mysql_insert_id during registration to get id for new user. But after deletion of 21th row during nex registration process mysql_insert_id gave me number 21. but stored in 24th row. And put to associations table 21 for new user. I wanna solve this problem
When you use an autoincrement id column, the value that the next entry will be assigned will not be reduced by deleting an entry. That is not what an autoincrement column is used for. The database engine will always increment that number on a new insert and never decrement that number on a delete.
A MySQL auto_increment column maintains a number internally, and will always increment it, even after deletions. If you need to fill in an empty space, you have to handle it yourself in PHP, rather than use the auto_increment keyword in the table definition.
Rolling back to fill in empty row ids can cause all sorts of difficulty if you have foreign key relationships to maintain, and it really isn't advised.
The auto_increment can be reset using a SQL statement, but this is not advised because it will cause duplicate key errors.
-- Doing this will cause problems!
ALTER table AUTO_INCREMENT=12345;
EDIT
To enforce your foreign key relationships as described in the comments, you should add to your table definition:
FOREIGN KEY (friendid) REFERENCES registration_table (id) ON DELETE SET NULL;
Fill in the correct table and column names. Now, when a user is deleted from the registration, their friend association is nulled. If you need to reassociate with a different user, that has to be handled with PHP. mysql_insert_id() is no longer helpful.
If you need to find the highest numbered id still in the database after deletion to associate with friends, use the following.
SELECT MAX(id) FROM registration_table;
Auto increment is a sequence key that's tracked as part of the table. It does not go back when you delete a row.
Easily, no. What you can do (but I don't suggest doing) is making an SQL function to determine the lowest number that isn't currently occupied. Or you can create a table of IDs that were deleted, and get the smallest number from there. Or, and this is the best idea, ignore the gaps and realize the database is fine.
What you want to do is achievable by adding an extra column to your table called something like user_order. You can then write code to manage inserts and deletions so that this column is always sequential with no gaps.
This way you avoid the problems you could have messing around with an auto_increment column.
It's not a good practice to reset auto_increment value, but if you really need to do it, so you can:
ALTER TABLE mytable AUTO_INCREMENT = 1;
Run this query after every delete. Auto_increment value will not be set to 1, this will set the lowest possible value automatically.
I am writing a sql editor (sqlite3).
I can display a table and allow users to edit any value in the table but I now need some way of identifying the value editted. The problem is that I don't know what the primary key is and I don't think it's that good an idea to say "update table set a=b where x=123 and y=123 and z=123 and..." for all the fields that aren't "a".
I'm using jquery (and ajax) and php.
Any ideas?
If you don't know what the primary key is (or you don't know if there is an UNIQUE index), you won't have much of a choice : even if using all fields in your where clause, you might update more than one line (the one the user wanted to edit).
You really need some way to identify one precise line -- and that way is the primary key.
Maybe, just out of curiosity, you my check how phpMyAdmin does that ?
(I know it's not SQLIte, my MySQL -- but maybe the general idea could be re-used ?)
You could force the user to specify a primary key (or at least a UNIQUE) and then retrieve it with SHOW INDEX FROM table (http://dev.mysql.com/doc/refman/5.0/en/show-index.html)
If you cannot determine PK or UK column then you have to use "where x=123 and y=123 and z=123", but remember to add LIMIT 1 - then you are sure you don't edit more than one record.
It is indeed not such a good idea to issue that update '... for all the fields that aren't a'. You should include a too, along with the old value of a in the row that was edited.
I have an issue in mysql that i have a field id which is auto increment and some other fields. where the id field should not be autoincremented while enterting the null values and should be autoincremented while entering values insert values in the same row while giving not null values .
It sounds like you need to generate the value for the id field yourself, in your own code, rather than having the database generate it.
If you create an identity field in the database, the database will create the field automatically. Generally this occurs when the record is saved, whether there are null fields present or not. If you need more control than this, you have to generate the id values yourself.
If you need to know what the next id number is, you can get it with SELECT MAX(id_field);
Robert Harvey's answer tackles the problem but I would also suggest looking at what you are saving and see if there is another approach. Perhaps the null values should be saved in another table? Perhaps the column you have as auto-increment isn't the primary key.
This may not be the direction but in this case it's worth stepping back and re-examining.