I have a table with autoincremented columnd 'id'.
The current AUTO_INCREMENT value is 99. So the next element, inserted to this table will have id=99.
I need to add a 1000 rows, forcing their ids to 2000-3000, and then reserve these values to not mess with others. I mean, after inserting these rows, I would like to return AUTO_INCREMENT value to 99, so that next row will have value 99, after that 100 and so on.
Regular ids will not raise higher than 1000, so I want them to get incremented in normal way.
I know it looks not so elegant, but it would make things a lot easier for a particular task.
Is is possible at all?
I need to add a 1000 rows, forcing their ids
Nope, You Don't
Autoincrement field is not what you think. It's unique identifier that's have no particular meaning at all. So - just leave it alone. If you want some sort of meaningful identifier - add another field and play with it whatever way you want.
Is is possible at all?
Fortunately - no.
Related
I'm looking to add a sort INT UNSIGNED field to my table so I can sort the items depending on their order without touching their id. Is it possible to give this column a value much like auto_increment but instead of incrementing by 1, MySQL increments by 10 or 20 or even 30? The large gaps allow me to shuffle their order.
I may be thinking about this the wrong way so please tell me what you think.
In fact, there is absolutely no need in "large gaps".
You can always swap 2 numbers - that's enough for the user-defined sorting.
Just update your sorting field to the same value with id initially and then move it to whatever position.
You can do that by changing auto_increment_increment:
SET ##auto_increment_increment=10;
More information
There is one issue: typically, for each table there can be only one column with auto_increment - if you have an id column that's also auto_increment - which really have much better reason to be auto_increment, this whole idea won't cut.
Secondly, it probably does not make much sense any way, since there is no reason for the latest inserted row (by default) to have the highest sorting order.
appart from setting the autoincrement to 10 like suggested you should also consider make it a unique key to speed up sorting.
I have a table with the column name id and the settings of both PRIMARY KEY and AUTO INCREMENT. When a row is deleted mid-way through the table, i.e. row 29 in rows 1 - 70, id 29 will simply disappear. Is it possible to have it so that the rows shift up, but the id remains there, i.e. deleting 70 instead of 29, so that the row that had id 30 will now adopt 29, 31 will adopt 30 etc?
This will make it a lot easier when inserting new data into the table in my case if this is possible.
I'm really looking to have the values used up before a new one is created, so it's either this which would be great, or looking for missing values and updating them.
UPDATE:
I wanted this to say, get the row above a certain row, and if all the id columns were in straight value order (no gaps) then I'd be able to do it relatively easily.
In general, it's a hassle to update primary keys in a database since this often sets of a chain of updates through all the tables which reference that primary key. Many engines allow you to force this update to happen automatically using the CASCADE option but it still results in a lot of otherwise unnecessary database updating.
The normal use of auto-incrementing integer primary keys is as permanent, meaningless, immutable values.
That said, if you really want to update those keys, you could do so with the command
UPDATE YourTable SET id = id - 1 WHERE id > (value you deleted)
Alternatively, you can maintain a second integer column, not the primary key of the table, and update this column after each deletion.
answer to the edited question
Previous ID:
SELECT id FROM $mytable WHERE id < $id ORDER BY ID DESC LIMIT 1;
Next ID:
SELECT id FROM $mytable WHERE id > $id ORDER BY ID ASC LIMIT 1;
This will make it a lot easier when inserting new data into the table
in my case if this is possible.
It shouldn't make any difference in your inserts. The column is an auto increment, so it's an unspecified column in your inserts. How does a gap at 29 make it any more or less difficult to insert your 1000th record?
On top of that, if you're re-assigning values to the column that is your primary key, you lose all referential integrity for any tables that reference that column.
To answer your question directly, you can simply drop the auto increment column and recreate it. It'll re-start the numbering at 1 and remove the gaps. However, I strongly recommend against doing this since it's completely unnecessary.
Auto-increment primary keys need to be unique, but they don't need to be contiguous.
You're trying to solve a problem that does not need to be solved. Gaps in auto-increment primary keys are okay. You don't need them to be contiguous. Trying to make them contiguous causes more problems:
It's costly to run queries to find gaps.
It's costly to update lots of rows to shift primary key values to fill the gap. What if you have 10 million rows, and there's a gap after row 2?
It's likely that you'll get a new INSERT while you're shifting values. Now you have to shift again.
If you shift rows to fill the gap, don't forget to ALTER TABLE to change the next auto-increment value that will be generated. Now you have to run two UPDATEs and a table-locking ALTER after every DELETE, which is terrible for scalability.
If you re-use primary key values, you'll confuse your application. It may have deleted a row for a reason. If an application searches for a value based on the primary key, it should find that the row was deleted. It should not find some other arbitrary row that has been shifted into that place.
If you need primary keys to be contiguous, then you're using them as a de facto COUNT, or else some kind of ranking. This is not what the auto-increment mechanism is designed to do.
I have a table in my phpmyadmin that contains some data for items that will be posted on a website. I'm adding these rows to the database manually. I want to show the number of the posted item. The first one will be '1', second one will be '2', etc. However if I use auto increment and delete the 2nd row there will be a gap in between. Suggestions to fix this?
I used PHP to display the ID of the row but when the second is deleted it shows the gap.
The structure starts with a column named 'id' which has a primary key and auto increment.
You don't want to do that! Period. You'll create yourself a lot of problems.
Your real issue is somewhere else. You think not having gaps between your ids will solve it. Solve that problem differently but leave the autoincremented id column alone. It is being implemented like that for a reason. The autoincrement makes sure you will never confuse two entries, it doesn't matter if there are gaps, you can always sort, you can always identify! If you need nice straight numbers, store your entries in a numeric array and use the keys for numbering. Or loop over your entries with a for loop and use the incrementor for numbering, or introduce an order column in your database.
Suggestions to fix this?
It's not broken!
You should not care or consider database ids as a developer, it is for internal use and data integrity.
If you really want to use incrementing numbers without gaps, use this in your query:
LIMIT 1 OFFSET X
Where X is the "id" in your url (not the real id).
However, listen to the folks here that are advising against this. It's not a very good idea and trust me, no one will care or even notice the forward facing database ids.
Okay, so let's say I have a mysql database table with two columns, one is for id and the other is for password. If I have three rows of data and the id values go from 1 to 3 and I delete row 3 and then create another row of data, I will see id=4 instead of id=3 on the newly created row. I know this has to do with the auto increment value but I was wondering if I can add some code in a php file that will automatically reset all the id numbers such that you start at id=1 and go up to the last id number in increments of 1 after a row has been deleted?
My goal is to create a form where the user enters a password and the system will match the password with a password value in the database. If there is a match, the row with the matched password will be deleted and the column of id numbers will be reordered such that no id numbers are skipped.
Update: I'm making a rotating banner ad system by setting a random number from 1 to 4 to a variable so that the php file will retrieve a random ad from id=1 to id=4 by using the random number variable. If the random number happens to be 3 and id=3 does not exist, there will be a gap in the row of banner ads. If there is a way to work around big gaps in this situation, please tell me. thanks in advance
Just execute the following SQL query:
ALTER TABLE `tbl_name` AUTO_INCREMENT = 1;
…but it sounds like a terrible idea, so don't do it. Why is the value of your primary key so important? Uniqueness is far more important, and reseting it undermines that.
You can only use
ALTER TABLE 'tbl' AUTO_INCREMENT=#
to reset to a number above the highest value number. If you have 1, 2, 3, and you delete 2, you cannot use this to fill 2. If you delete 3, you could use this to re-use 3 (assuming you haven't put anything higher). That is the best you can do.
ALTER TABLE 'table' AUTO_INCREMENT = 1;
However running this code is not the best idea. There is something wrong with your application if you depend on the column having no gaps. Are you trying to count the number of users? if so use COUNT(id)? Are you trying to deal with other tables? If so use a foreign key.
If you are dead set on doing this the Wrong Way you could try to look for the lowest free number and do the incrementing on your own. Keep in mind the race conditions involves however.
Also, keep in mind that if you change the actual numbers in the database you will need to change all references to it in other tables and in your code.
Well, you can actually just specify the id number you'd like a record to have as part of your insert statement, for example:
INSERT INTO person VALUES(1,'John','Smith','jsmith#devnull.fake','+19995559999');
And if there's not a primary key collision (no record in the database with id=1), then MySQL will happily execute it.
The ALTER TABLE 'tbl' AUTO_INCREMENT=# thing also works, and means you don't have to keep track of the counter.
While you're thinking about this, though, you might want to read some of the discussion on natural vs surrogate keys. The idea of having your id # be specifically important is a bit unusual and might be a sign of a troubled design.
You could do that by:
Inventing a mechanism that provides the next available id when you want to insert (e.g. a transaction involving reading and incrementing an integer column somewhere -- pay special attention to the transaction isolation level!)
Using UPDATE to decrement all ids greater than the one you just deleted (again, with a transaction -- don't forget that foreign keys must be ON UPDATE CASCADE!)
But it begs the question: why do you want this? is it going to be worth the trouble?
It's almost certain that you can achieve whatever your goal is without such witchery.
Update (to address comment):
To select a random number of rows, you can do e.g. in MySQL
SELECT id FROM banners ORDER BY RAND() LIMIT 5
to select 5 random, guaranteed existing banner ids.
A word of caution: there are quite a few people who view ORDER BY RAND() as a bad performance hog. However, it is IMHO not quite right to put every case in the same basket. If the number of rows in the table is manageable (I would consider anything below 10K to be not that many) then ORDER BY RAND() provides a very nice and succint solution. Also, the documentation itself suggests this approach:
However, you can retrieve rows in
random order like this:
mysql> SELECT * FROM tbl_name ORDER BY RAND();
ORDER BY RAND() combined with
LIMIT is useful for selecting a random
sample from a set of rows:
mysql> SELECT * FROM table1, table2 WHERE a=b AND c ORDER BY RAND() LIMIT 1000;
RAND() is not meant to be
a perfect random generator. It is a
fast way to generate random numbers on
demand that is portable between
platforms for the same MySQL version.
I want to build a database-wide unique id. That unique id should be one field of every row in every table of that database.
There are a few approaches I have considered:
Create one master-table with an auto-increment-field and a trigger in every other table, like:
"before insert here, insert in master-table -> get the auto-increment value -> and use this value as primary-key here"
I have seen this before, but instead of making one INSERT, it does 2 INSERTS, which I expect would not be that performant.
Add a field uniqueId to every table, and fill this field with a PHP-generated integer... something like unix-timestamp plus a random number.
But I had to use BIGINT as the datatype, which means big index_length and big data_length.
Similar to the "uniqueId" idea, but instad of BIGINT I use VARCHAR and use uniqid() to populate this value.
Since you are looking for opinions... Of the three ideas you give, I would "vote" for the uniqid() solution. It seems pretty low cost in terms of execution (but possibly not implementation).
A simpler solution (I think) would be to just add a field to each table to store a guid and set the default value of the field to be MySQL's function that generates a guid (I think it is UUID). This lets the database do the work for you.
And in the spirit of coming up with random ideas... It would be possible to have some kind of offline process fill in the IDs asynchronously. Make sure every table has the appropriate field and make the default value be 0/empty. Then the offline process could simply run a query on each table to find the rows that do not yet have a unique id and it could fill them in. That would let you control the ID and even use some kind of incrementing integer. This, of course, requires that you do not need the unique ID instantly each time a record is inserted.