Change Column to Auto_Increment - php

I asked this question a little earlier today but am not sure as to how clear I was.
I have a MySQL column filled with ordered numbers 1-56. These numbers were generated by my PHP script, not by auto_increment.
What I'd like to do is make this column auto_incrementing after the PHP script sets the proper numbers. The PHP script works hand in hand with a jQuery interface that allows me to reorder a list of items using jQuery's UI plugin.
Once I decide what order I'd like the entries in, I'd like for the column to be set to auto increment, such that if i were to insert a new entry, it would recognize the highest number already existing in the column and set its own id number to be one higher than what's already existing.
Does anyone have any suggestions on how to approach this scenario?

I'd suggest creating the table with your auto_increment already in place. You can specify a value for the auto_inc column, and mysql will use it, and still the next insert to specify a NULL or 0 value for the auto_inc column will magically get $highest + 1 assigned to it.
example:
mysql> create table foobar (i int auto_increment primary key);
mysql> insert into foobar values (10),(25);
mysql> insert into foobar values (null);
mysql> select * from foobar;
# returns 10,25,26

You can switch it to MySQL's auto_increment implementation, but it'll take 3 queries to do it:
a) ALTER TABLE to add the auto_increment to the field in question
b) SELECT MAX(id) + 1 to find out what you need to set the ID to
c) ALTER TABLE table AUTO_INCREMENT =result from (b)
MySQL considers altering the AUTO_INCREMENT value a table-level action, so you can't do it in (a), and it doesn't allow you to do MAX(id) in (c), so 3 queries.

You can change that with a query, issued through php, using the mysql console interface or (easiest) using phpmyadmin.
ALTER TABLE table_name CHANGE old_column_name new_column_name column_definition;
ALTER TABLE table_name AUTO_INCREMENT = highest_current_index + 1
column_definiton:
old_column_definition AUTO_INCREMENT
More info:
http://dev.mysql.com/doc/refman/5.1/en/alter-table.html
http://dev.mysql.com/doc/refman/5.1/en/create-table.html
EDIT
Always use mysql_insert_id or the appropiate function of your abstraction layer to get the last created id, as LAST_INSERT_ID may lead to wrong results.

No, stop it. This isn't the point of auto_increment. If you aren't going to make them ordered by the id then don't make them auto_increment, just add a column onto the end of the table for ordering and enjoy the added flexibility it gives you. It seems like you're trying to pack two different sets of information into one column and it's really only going to bite you in the ass despite all the well-meaning people in this thread telling you how to go about shooting yourself in the foot.

In MySQL you can set a custom value for an auto_increment field. MySQL will then use the highest auto_increment column value for new rows, essentially MAX(id)+1. This means you can effectively reserve a range of IDs for custom use. For instance:
CREATE TABLE mytable (
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
col1 VARCHAR(256)
);
ALTER TABLE mytable AUTO_INCREMENT = 5001;
In this schema all ids < 5001 are reserved for use by your system. So, your PHP script can auto-generate values:
for ($i=1; $i<=56; $i++)
mysql_query("INSERT INTO mytable SET id = $i, col1= 'whatevers'");
New entries will use the non-reserved range by not specifying id or setting it to null:
INSERT INTO mytable SET id = NULL, col1 = 'whatevers2';
-- The id of the new row will be 5001
Reserving a range like this is key - in case you need more than 56 special/system rows in the future.

ALTER TABLE <table name> <column name> NOT NULL AUTO_INCREMENT
More info:
AUTO_INCREMENT Handling in InnoDB
Server SQL Modes

Related

How would I go about automatically shifting the auto-increment id element in my sql table after I delete an element? [duplicate]

How would I reset the primary key counter on a sql table and update each row with a new primary key?
I would add another column to the table first, populate that with the new PK.
Then I'd use update statements to update the new fk fields in all related tables.
Then you can drop the old PK and old fk fields.
EDIT: Yes, as Ian says you will have to drop and then recreate all foreign key constraints.
Not sure which DBMS you're using but if it happens to be SQL Server:
SET IDENTITY_INSERT [MyTable] ON
allows you to update/insert the primary key column. Then when you are done updating the keys (you could use a CURSOR for this if the logic is complicated)
SET IDENTITY_INSERT [MyTable] OFF
Hope that helps!
This may or not be MS SQL specific, but:
TRUNCATE TABLE resets the identity counter, so one way to do this quick and dirty would be to
1) Do a Backup
2) Copy table contents to temp table:
3) Copy temp table contents back to table (which has the identity column):
SELECT Field1, Field2 INTO #MyTable FROM MyTable
TRUNCATE TABLE MyTable
INSERT INTO MyTable
(Field1, Field2)
SELECT Field1, Field2 FROM #MyTable
SELECT * FROM MyTable
-----------------------------------
ID Field1 Field2
1 Value1 Value2
Why would you even bother? The whole point of counter-based "identity" primary keys is that the numbers are arbitrary and meaningless.
you could do it in the following steps:
create copy of yourTable with extra column new_key
populate copyOfYourTable with the affected rows from yourTable along with desired values of new_key
temporarily disable constraints
update all related tables to point to the value of new_key instead of the old_key
delete affected rows from yourTable
SET IDENTITY_INSERT [yourTable] ON
insert affected rows again with the new proper value of the key (from copy table)
SET IDENTITY_INSERT [yourTable] OFF
reseed identity
re-enable constraints
delete the copyOfYourtable
But as others said all that work is not needed.
I tend to look at the identity type primary keys as if they were equivalent of pointers in C, I use them to reference other objects but never modify of access them explicitly
If this is Microsoft's SQL Server, one thing you could do is use the [dbcc checkident](http://msdn.microsoft.com/en-us/library/ms176057(SQL.90).aspx)
Assume you have a single table that you want to move around data within along with renumbering the primary keys. For the example, the name of the table is ErrorCode. It has two fields, ErrorCodeID (which is the primary key) and a Description.
Example Code Using dbcc checkident
-- Reset the primary key counter
dbcc checkident(ErrorCode, reseed, 7000)
-- Move all rows greater than 8000 to the 7000 range
insert into ErrorCode
select Description from ErrorCode where ErrorCodeID >= 8000
-- Delete the old rows
delete ErrorCode where ErrorCodeID >= 8000
-- Reset the primary key counter
dbcc checkident(ErrorCode, reseed, 8000)
With this example, you'll effectively be moving all rows to a different primary key and then resetting so the next insert takes on an 8000 ID.
Hope this helps a bit!

How can I reset id to 0 in PHP MYSQL? [duplicate]

How can I reset the AUTO_INCREMENT of a field?
I want it to start counting from 1 again.
You can reset the counter with:
ALTER TABLE tablename AUTO_INCREMENT = 1
For InnoDB you cannot set the auto_increment value lower or equal to the highest current index. (quote from ViralPatel):
Note that you cannot reset the counter to a value less than or equal
to any that have already been used. For MyISAM, if the value is less
than or equal to the maximum value currently in the AUTO_INCREMENT
column, the value is reset to the current maximum plus one. For
InnoDB, if the value is less than the current maximum value in the
column, no error occurs and the current sequence value is not changed.
See How can I reset an MySQL AutoIncrement using a MAX value from another table? on how to dynamically get an acceptable value.
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
Simply like this:
ALTER TABLE tablename AUTO_INCREMENT = value;
Reference: 13.1.9 ALTER TABLE Statement
There is a very easy way with phpMyAdmin under the "operations" tab. In the table options you can set autoincrement to the number you want.
The best solution that worked for me:
ALTER TABLE my_table MODIFY COLUMN ID INT(10) UNSIGNED;
COMMIT;
ALTER TABLE my_table MODIFY COLUMN ID INT(10) UNSIGNED AUTO_INCREMENT;
COMMIT;
It's fast, works with InnoDB, and I don't need to know the current maximum value!
This way. the auto increment counter will reset and it will start automatically from the maximum value exists.
The highest rated answers to this question all recommend "ALTER yourtable AUTO_INCREMENT= value". However, this only works when value in the alter is greater than the current max value of the autoincrement column. According to the MySQL 8 documentation:
You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.
In essence, you can only alter AUTO_INCREMENT to increase the value of the autoincrement column, not reset it to 1, as the OP asks in the second part of the question. For options that actually allow you set the AUTO_INCREMENT downward from its current max, take a look at Reorder / reset auto increment primary key.
As of MySQL 5.6 you can use the simple ALTER TABLE with InnoDB:
ALTER TABLE tablename AUTO_INCREMENT = 1;
The documentation are updated to reflect this:
13.1.7 ALTER TABLE Statement
My testing also shows that the table is not copied. The value is simply changed.
Beware! TRUNCATE TABLE your_table will delete everything in your your_table.
You can also use the syntax TRUNCATE table like this:
TRUNCATE TABLE table_name
ALTER TABLE news_feed DROP id
ALTER TABLE news_feed ADD id BIGINT( 200 ) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KEY (id)
I used this in some of my scripts. The id field is dropped and then added back with previous settings. All the existent fields within the database table are filled in with the new auto increment values. This should also work with InnoDB.
Note that all the fields within the table will be recounted and will have other ids!!!.
It is for an empty table:
ALTER TABLE `table_name` AUTO_INCREMENT = 1;
If you have data, but you want to tidy up it, I recommend to use this:
ALTER TABLE `table_name` DROP `auto_colmn`;
ALTER TABLE `table_name` ADD `auto_colmn` INT( {many you want} ) NOT NULL AUTO_INCREMENT FIRST ,ADD PRIMARY KEY (`auto_colmn`);
To update to the latest plus one id:
ALTER TABLE table_name AUTO_INCREMENT =
(SELECT (id+1) id FROM table_name order by id desc limit 1);
Edit:
SET #latestId = SELECT MAX(id) FROM table_name;
SET #nextId = #latestId + 1;
ALTER TABLE table_name AUTO_INCREMENT = #nextId;
Not tested please test before you run*
Warning: If your column has constraints or is connected as a foreign key to other tables this will have bad effects.
First, drop the column:
ALTER TABLE tbl_name DROP COLUMN column_id
Next, recreate the column and set it as FIRST (if you want it as the first column I assume):
ALTER TABLE tbl_access ADD COLUMN `access_id` int(10) NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST
As of MySQL 5.6 the approach below works faster due to online DDL (note algorithm=inplace):
alter table tablename auto_increment=1, algorithm=inplace;
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
ALTER TABLE tablename AUTO_INCREMENT = 1
Try to run this query:
ALTER TABLE tablename AUTO_INCREMENT = value;
Or try this query for the reset auto increment
ALTER TABLE `tablename` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL;
And set auto increment and then run this query:
ALTER TABLE `tablename` CHANGE `id` `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT;
The auto-increment counter for a table can be (re)set in two ways:
By executing a query, like others already explained:
ALTER TABLE <table_name> AUTO_INCREMENT=<table_id>;
Using Workbench or another visual database design tool. I am going to show in Workbench how it is done - but it shouldn't be much different in other tools as well. By right clicking over the desired table and choosing Alter table from the context menu. On the bottom you can see all the available options for altering a table. Choose Options and you will get this form:
Then just set the desired value in the field Auto increment as shown in the image. This will basically execute the query shown in the first option.
If you're using PHPStorm's database tool you have to enter this in the database console:
ALTER TABLE <table_name> AUTO_INCREMENT = 0;
I tried to alter the table and set auto_increment to 1 but it did not work. I resolved to delete the column name I was incrementing, then create a new column with your preferred name and set that new column to increment from the onset.
I googled and found this question, but the answer I am really looking for fulfils two criteria:
using purely MySQL queries
reset an existing table auto-increment to max(id) + 1
Since I couldn't find exactly what I want here, I have cobbled the answer from various answers and sharing it here.
Few things to note:
the table in question is InnoDB
the table uses the field id with type as int as primary key
the only way to do this purely in MySQL is to use stored procedure
my images below are using SequelPro as the GUI. You should be able to adapt it based on your preferred MySQL editor
I have tested this on MySQL Ver 14.14 Distrib 5.5.61, for debian-linux-gnu
Step 1: Create Stored Procedure
create a stored procedure like this:
DELIMITER //
CREATE PROCEDURE reset_autoincrement(IN tablename varchar(200))
BEGIN
SET #get_next_inc = CONCAT('SELECT #next_inc := max(id) + 1 FROM ',tablename,';');
PREPARE stmt FROM #get_next_inc;
EXECUTE stmt;
SELECT #next_inc AS result;
DEALLOCATE PREPARE stmt;
set #alter_statement = concat('ALTER TABLE ', tablename, ' AUTO_INCREMENT = ', #next_inc, ';');
PREPARE stmt FROM #alter_statement;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
Then run it.
Before run, it looks like this when you look under Stored Procedures in your database.
When I run, I simply select the stored procedure and press Run Selection
Note: the delimiters part are crucial. Hence if you copy and paste from the top selected answers in this question, they tend not to work for this reason.
After I run, I should see the stored procedure
If you need to change the stored procedure, you need to delete the stored procedure, then select to run again.
Step 2: Call the stored procedure
This time you can simply use normal MySQL queries.
call reset_autoincrement('products');
Originally from my own SQL queries notes in https://simkimsia.com/reset-mysql-autoincrement-to-max-id-plus-1/ and adapted for Stack Overflow.
delete from url_rewrite where 1=1;
ALTER TABLE url_rewrite AUTO_INCREMENT = 1;
and then reindex
ALTER TABLE `table_name` DROP `id`;
ALTER TABLE `table_name` ADD `id` INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (`id`) ;
Shortly,First we deleted id column then added it with primary key id again...
The best way is remove the field with AI and add it again with AI. It works for all tables.
You need to follow the advice from Miles M's comment and here is some PHP code that fixes the range in MySQL. Also you need to open up the my.ini file (MySQL) and change max_execution_time=60 to max_execution_time=6000; for large databases.
Don’t use "ALTER TABLE tablename AUTO_INCREMENT = 1". It will delete everything in your database.
$con = mysqli_connect($dbhost, $dbuser, $dbpass, $database);
$res = mysqli_query($con, "select * FROM data WHERE id LIKE id ORDER BY id ASC");
$count = 0;
while ($row = mysqli_fetch_array($res)){
$count++;
mysqli_query($con, "UPDATE data SET id='".$count."' WHERE id='".$row['id']."'");
}
echo 'Done reseting id';
mysqli_close($con);
I suggest you to go to Query Browser and do the following:
Go to schemata and find the table you want to alter.
Right click and select copy create statement.
Open a result tab and paste the create statement their.
Go to the last line of the create statement and look for the Auto_Increment=N,
(Where N is a current number for auto_increment field.)
Replace N with 1.
Press Ctrl + Enter.
Auto_increment should reset to one once you enter a new row in the table.
I don't know what will happen if you try to add a row where an auto_increment field value already exist.

Mysql Truncate Table, Auto Increment not working

So i just truncated my table but now my primary key will not auto increment. Every time I add a 2nd item to the table, it comes back with 1062: Duplicate entry '0' for key 'PRIMARY'
I thought when you truncate a table it will just resets the auto increment back to 1.
I search around on what I could do but I have come across many people saying just truncate.
What I did
"TRUNCATE TABLE mytable;"
I must have done something wrong.
This bug not affects Mysql 5.0 and it is repeatable on 6.0 and 5.1.23 and 5.1BK.
Refer this link for proof
Following is readily available and effective workaround is to ALTER the autoinc value after the table is truncated.
Re-initialize the autoinc value right after truncation
alter table tablename AUTO_INCREMENT = n; /* set n as desired */
From MySQL 5.0.13 , the AUTO_INCREMENT counter is reset to zero by TRUNCATE TABLE, regardless of whether there is a foreign key constraint.
All you need to do is:
SET FOREIGN_KEY_CHECKS=0;
truncate your tables and change it back to
SET FOREIGN_KEY_CHECKS=1;
Once TRUNCATE is fired, the table handler does not remember the last used AUTO_INCREMENT value, but starts counting from the beginning.
This is true even for MyISAM and InnoDB, which normally do not reuse sequence values.
User this Query it will work.
ALTER TABLE table_name CHANGE table_id table_id INT( 11 ) NOT NULL AUTO_INCREMENT

Mysql reset auto_increment not for new ids but for all (also old ids)

Hi all is there any SQL function to reset all auto_increment ids?
I mean , i have this situation (id =1 , id2 = 2, id3 =3)
once i delete id i would like to be returned this situation (id2 = 1, id3 = 2) and so on.
Need i a script to do that?
You can reset the AUTO_INCREMENT for the whole table:
ALTER TABLE table AUTO_INCREMENT=1;
But you cannot really go back to fill in values in individual rows that have been deleted. The auto_increment values are intended to be unique, but aren't guaranteed to remain sequential if deletions happen or new rows are inserted with an explicit value set for the auto_increment column.
If you needed to modify them to be sequential again, it would have to be done in code, probably looping over all rows and performing UPDATE statements individually.
Id is Id which means it must never change! At least in good database design. Id is something you are born with and you die with.

Increment value on new row

Given this table design in a web application:
CREATE TABLE `invoice` (
`invoice_nr` int(10) unsigned NOT NULL AUTO_INCREMENT,
`revision` int(10) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`invoice_nr`,`revision`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci
What's the most handy and reliable way to insert a new invoice revision and get back the assigned revision number?
The first obvious approach strikes me as unreliable in a shared environment:
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
This alternative looks slightly better (I don't know if it's actually better):
INSERT INTO invoice (invoice_nr, revision)
SELECT 31416, MAX(revision)+1
FROM invoice
WHERE invoice_nr = 31416;
... but I can't know the revision number unless I run a new query:
SELECT MAX(revision) AS last_revision
FROM invoice
WHERE invoice_nr = 31416;
Is there a recommended method?
App runs on PHP with good old mysql extension--mysql_query() et al.
Mysql has a function called last_insert_id() that returns the last auto generated ID. So you can just SELECT last_insert_id() straight after inserting your data.
PHP has a built in function for doing this called mysql_insert_id().
More on that here: http://www.php.net/manual/en/function.mysql-insert-id.php
Whilst that's all true and generally useful it's not actually what's being looked for here. How I'd do this is generate to tables. One called invoice with you auto increment field and a second called invoice_revisions. This should have the same format as the invoice table with the added vision field.
Then when you update your invoice table you first do:
INSERT INTO invoice_revision SELECT i.*,IFNULL(max(ir.revision),0)+1 AS revision FROM invoice i LEFT JOIN invoice_revision ir on ir.invoice_nr = i.invoice_nr WHERE i.invoice_nr = ?
Then update your invoice table as normal. This way you have your up to date data in the invoice table and the list of all the previous versions in the invoice_revisions table.
Note if you are using Myisam tables you and set the revision at the auto_increment in that table:
http://dev.mysql.com/doc/refman/5.5/en/example-auto-increment.html
if you put a properly isolated transaction around your insert and select nobody may alter these tables between both statements.
another approach is to use a stored procedure to execute both commands and return the result.
I've gathered a couple of techniques from the MySQL manual. I thought I should share them here for the records.
1. Table locking
If you place a lock on the table, other simultaneous processes will be queued. Then, you don't need any special trick to avoid dupes:
LOCK TABLES invoice WRITE;
SELECT MAX(revision)+1 AS next_revision -- E.g. 2
FROM invoice
WHERE invoice_nr = 31416;
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, 2);
-- Or INSERT INTO ... SELECT
UNLOCK TABLES;
2. LAST_INSERT_ID(expr)
The LAST_INSERT_ID() function accepts an optional parameter. If set, it returns such value and it also stores it for the current session so next call to LAST_INSERT_ID() will return that value. This is a handy way to emulate sequences:
CREATE TABLE `sequence` (
`last_value` INT(50) UNSIGNED NOT NULL DEFAULT '1' COMMENT 'Last value used'
);
START TRANSACTION;
UPDATE sequence
SET last_value=LAST_INSERT_ID(last_value+1);
INSERT INTO invoice (invoice_nr, revision)
VALUES (31416, LAST_INSERT_ID());
COMMIT;

Categories