I have a table in my db where I store records of user actions. Currently the column that contains user IDs is set to int(11), however i am making some changes to my code where I will be adding temporary user IDs.
To differentiate the temporary IDs from the regular ones, I prepend 0 to the id.
Example: 4 -- regular user; 023 -- temporary
However when I populate this ID into ym table the zero gets discarded. What field type do I need to change it to to keep all IDs in tact?
You could change it to an varchar if you want to prefix the id's with a 0
But you might want to try this.
Add a new column:
ALTER TABLE `your_table` ADD COLUMN `temp_id` INT(11) NULL AFTER `original_id`;
Then migrate your id's
UPDATE `your_table` SET temp_id = `original_id`;
I think you'll have to go with a varchar field but note that this will eliminate your auto_increment if you have one.
The user ID is an int and ints are binary numbers. A leading zero is the SAME as the number without a leading zero.
I would suggest negating the number to indicate a temporary id.
You can't add a 0 before an int ( (01 == 1) -- mostly but I'm not going to get into the vagaries of that).
Just add a type column. You can always drop the column later.
Related
I have a table with a bunch of rows whose ID's are numbers with value less than 20,000,000. The table structure looks like this:
CREATE TABLE records(
id int(11) not null AUTO_INCREMENT,
... more data columns ...
) ENGINE=InnoDB AUTO_INCREMENT=16432352 DEFAULT CHARSET=utf8;
A system that is out of my control inserts rows in this table and the database insert those records with a generated ID.
But, I need to insert records in this table with very big ID's (starting 50,000,000). Also, it's important to note that the uncontrolled system inserts few records, such that the records I'm going to insert never collides with the records of the uncontrolled system.
Making some tests I realized that when I insert a record with a very vig ID, the AUTO_INCREMENT value jumps to that very big ID. For example:
First, I check the initial_auto_increment value:
SHOW TABLE STATUS FROM my-database like 'records';
... the auto_increment value looks like this:
# Name, ... , Auto_increment, ...
'record', ... , '16432352', ...
Next, I insert the record with a very big ID.
INSERT INTO records (id, ...) VALUES(679456755, ...);
Then, checking again the auto_increment value:
SHOW TABLE STATUS FROM my-database like 'records';
.. the final result look like this:
# Name, ... , Auto_increment, ...
'record', ... , '679456756', ...
My question is: How can I temporarily disable the AUTO_ICREMENT feature in such way that my records with very big ID's don't mess around with the AUTO_INCREMENT value of the table?
PS. I'm using MariaDB 10.
Edit: I changed the numbers, but the question is the same.
MySQL and MariaDB actually enforce the restriction AUTO_INCREMENT > MAX(id)
See ALTER TABLE Syntax
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.
You can use ALTER TABLE to set the AUTO_INCREMENT to any value higher than MAX(id) if you would like to store higher values, however you cannot set it to a lower value than one of the rows currently in the table.
If you need to create rows in a "gap", with lower IDs than the AUTO_INCREMENT value, you would need to explicitly specify the id value in your INSERT. But if a process beyond your control is inserting rows and not specifying the IDs then they are always going to obtain IDs higher than everything else currently in the table.
The only thing I can suggest, if you are able to adjust what IDs are used for what, is that you reserve low IDs for your purposes (so use, say, 1 to 10,000 instead of 50,000,000 to 50,009,999), set the AUTO_INCREMENT to 10,001 and then let the outside process use the higher IDs - this would work just fine provided you don't run out of space.
For a longer term solution, consider switching to UUIDs - though you would need to modify the process that is outside your control for this.
You can set the AUTO_INCREMENT to any value you please:
ALTER TABLE records AUTO_INCREMENT = ?
Though I'd strongly recommend burying records at high ID numbers. Usually lower is better, or just mixing them in with regular records. Being obsessive about these things leads to conflict later on when your assumptions end up being mistaken.
I have a 2 columns in my table: a varchar(8) and an int.
I want to auto-increment the int column and when I do, I want to copy the value into the varchar(8) column, but pad it with 0's until it is 8 characters long, so for example, if the int column was incremented to 3, the varchar(8) column would contain '00000003'.
My two questions are, what happens when the varchar(8) column gets to '99999999' because I don't want to have duplicates?
How would I do this in MySQL?
If my values can be between 00000000 to 99999999, how many values can i have before I run out?
This is my alternative approach to just creating a random 8 character string and checking MySQL for duplicates. I thought this was a better approach and would allow for a greater number of values.
Because your formatted column depends upon, and is derivable from, the id column, your table design violates 3NF.
Either create a view that has your derived column in it (see this in sqlfiddle):
CREATE VIEW myview AS
SELECT *, substring(cast(100000000 + id AS CHAR(9)), 2) AS formatted_id
FROM mytable
or just start your auto-increment at 10000000, then it will always be 8 digits long:
ALTER TABLE mytable AUTO_INCREMENT = 10000000;
Simple, if the column is unique, it will throw an exception telling that the value already do exists. But if not unique, after 99999999 you'll get error message that the value is truncated.
Alternatives, why not use INT AUTO_INCREMENT? or a custom ID with a combination of date/time, eg
YYMMDD-00000
This will have a maximum record of 99999 records per day. It will reset on the next day.
Lets say database has a table which has only two columns of ID which is Auto increment and name which is text. When we first add 2 names, then delete both of the names, next time again enter another name, the ID count starts from number 3 while it should start with number 1.
Question is that is there any way to reset the ID so that it starts from 0 once all values of ID's are removed instead of continuing increment from the last ID number that was removed?
Here's the SQL query to reset the AUTO_INCREMENT value:
ALTER TABLE tablename AUTO_INCREMENT = 0
You can use Truncate.
TRUNCATE TABLE yourtable;
It is similar to deleting all rows of your table but has some differences including resetting auto-increment to 0.
Yes you can
ALTER TABLE mytable AUTO_INCREMENT = 0
But why bother? There are plenty of numbers in the universe or even in 32 bits!
I think this will do what you are looking for.
ALTER TABLE table_name AUTO_INCREMENT = 1;
ALTER TABLE yourtable AUTO_INCREMENT = 1
There sure is!
ALTER TABLE 'mytable' AUTO_INCREMENT = 0;
This will reset the auto increment back down to 0 and continue from there.
A general note from MySQL-dev:
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.
I have a fairly large table with about 250k rows. It has an auto incremented ID column that is really sort of useless. I can't just get rid of the column without rewriting too much of the app, but the ID is never used as a foreign key or anything else (except simply as an identifier when you want to delete a row, I guess).
The majority of the data gets deleted and rewritten at least a few times a day (don't ask! it's not important, though I realize it's poor design!), though the total count of the rows stays fairly uniform. What this means is that each day to AI # increases by a quarter million or so.
My question is this: in several years' time, the ID column will get too large for the INT value. Is there a way to "reset" the ID, like an OPTIMIZE or something, or should I just plan on doing a SELECT INTO a temp table and truncating the original table, resetting the ID to 0?
Thanks
If you have the id as integer you can have 2^32 / 2 (2.147.483.647) rows, if is unsigned integer duplicate to 4.294.967.295, no worry 250.000 in nothing, if you want more, use unsigned bigint (18.446.744.073.709.551.615) :P
For reset the auto_numeric position:
ALTER TABLE table AUTO_INCREMENT = 1
Either change the datatype of ID to BIGINT and adjust your program accordingly, or if you're clearing everything out when you delete data you can use TRUNCATE TABLE TABLENAME which will reset the sequence.
Easiest and fastest :) Just drop the index, set autoincrement=1, and add it back :)
ALTER TABLE yourtable DROP id_field;
ALTER TABLE yourtable AUTO_INCREMENT=1;
ALTER TABLE yourtable ADD id_field INT NOT NULL AUTO_INCREMENT FIRST, ADD PRIMARY KEY (id_field);
I have a table with many rows but they are out of order. Im using the field "id" as the primary key. I also have a "date" field which is a datetime field.
How could i reindex the table so that the entries are id'd in chronological order according to the date field
How about something like a simple query using a variable:
set #ROW = 0;
UPDATE `tbl_example` SET `id` = #ROW := #ROW+1 ORDER BY `fld_date` ASC;
This will order your rows like: 0,1,2,4,5...etc by your date.
the way i would do it is to create a new table with auto increment index and just select all your old table into it ordering by date. you can then remove your old table.
Why do you want the sequence of IDs to correlate with the dates? It sounds like you want to do ORDER BY id and have the rows come back in date order. If you want rows in date order, just use ORDER BY date instead.
Values in an autoincrement ID column should be treated as arbitrary. Relying on your IDs being in date order is a bad idea.
The following SQL snippet should do what you want.
ALTER TABLE test_table ADD COLUMN id2 int unsigned not null;
SET #a:=0;
UPDATE test_table SET id2=#a:=#a+1 ORDER BY `date`;
ALTER TABLE test_table DROP id;
ALTER TABLE test_table CHANGE id2 id int UNSIGNED NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (id);
Keep in mind that you can never guarantee the order of an auto-incremented column once you start inserting and removing data, so you shouldn't be relying on any order except that which you specify using ORDER BY in your queries. This is an expensive operation that you are doing, as it requires indexes to be completely re-created, so I wouldn't suggest doing it often.
You can use ALTER TABLE t ORDER BY col;
The allowed syntax of ORDER BY is as in SELECT statements.
I had to do something similar. The best way to do it was the following (you can run it in one SQL Query if you want, but bare in mind that this is a slow and very resource consuming operation):
BE SURE TO MAKE A BACKUP OF YOUR TABLE, INCLUDING STRUCTURE AND DATA BEFORE STARTING THIS QUERY!
ALTER TABLE your_table ADD COLUMN temp_id INT UNSIGNED NOT NULL;
SET #a:=0;
UPDATE your_table SET temp_id=#a:=#a+1 ORDER BY `date` ASC;
ALTER TABLE your_table DROP id;
ALTER TABLE your_table CHANGE temp_id id INT UNSIGNED NOT NULL AUTO_INCREMENT, ADD PRIMARY KEY (id);
ALTER TABLE your_table CHANGE COLUMN id id INT(10) FIRST;
Just don't forget to change "your_table" with the name of your table, and the ORDER BY columns.
Here I explain you what you're doing this way step by step:
First you add a new column named "temp_id" (make sure it's not a name you're using already);
Next you add a temp variable equal to 0 (or to whatever you want for your ID to start from);
Then you update your table, row by row by the set ORDER logic, setting a value for your new column "temp_id" equal to the variable you've set, then increment this variable by 1 (you can do something funky here, for example if you want your ID's to be always even, the you can set #a+2);
Next step you drop (remove) your old column ID;
Then you change the name of your temp_id column back to ID and it as a positive integer with auto increment which is the primary key of your table.
Because ID now is the newly added temp_id column, it's located at the end of your table structure. To move it again as first column, you run the last query, to make sure it's the first column.
If you are using something like phpmysql this could be achieved by:
going to the table (left side list of db's and tables), then
from the options in the upper bar select 'SQL'. Follow the advice by #Ryun, then go to 'Operations' (from the upper bar),
look for 'TABLE OPTIONS', leave everything except 'AUTO_INCREMENT' unchanged,
set the 'AUTO_INCREMENT' value to 1 and press go at the bottom of the form.
What will this do, in all?
It will set the id columns in each from 1 to {count}.
Then it will reset the index of the table so that your next inserted row will equal +1 the number of columns (and not +1 the old index).
#Wyzard made reference to just ordering the columns by date when you retrieve them from the table (and not re-indexing). Since, indeed, the Primary Key should be arbitrary (except to any foreign keys and perhaps the consuming platform (but that is another matter)).