Rearrange primary keys in mysql - mysql

How to rearrange primary key column values after deleting some rows from a table in MySQL?
Foe example; a table with 4 row of data with primary key values 1,2,3,4. When delete 2nd and 3rd rows, then the key value of 4th row change to 2.
Please help me to find solution.

Why do this? You don't need to rearrange your key since it's only number, identifier for record. It has no actual meaning - so let DBMS handle that. This is a very common mistake - trying to take DBMS role.
However, I'll answer your question for common case. In MySQL you can rearrange column with:
update t cross join (select #cur:=0) as init set t.col=#cur:=#cur+1
-this, however, can't be used with column under UNIQUE (so primary key as well) restriction since during update you'll possibly get duplicate records. You should drop restriction first before do that (and create it again after update).

One method is THIS ONE.
Other then that, you can simply drop the table which is primary and then again create it. This will do the job

Why do you want to change primary keys for your data? In general this is bad idea to do that, especially when integrity contstraints comes into the game. If you need to do such thing, I would say you have bad DB desing and you should take closer look on that aspect.

Related

Auto-increment a primary key in MySql

During the creation of tables using mysql on phpmyadmin, I always find an issue when it comes to primary keys and their auto-increments. When I insert lines into my table. The auto_increment works perfectly adding a value of 1 to each primary key on each new line. But when I delete a line for example a line where the primary key is 'id = 4' and I add a new line to the table. The primary key in the new line gets a value of 'id = 5' instead of 'id = 4'. It acts like the old line was never deleted.
Here is an example of the SQL statement:
CREATE TABLE employe(
id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(30) NOT NULL
)
ENGINE = INNODB;
How do I find a solution to this problem ?
Thank you.
I'm pretty sure this is by design. If you had IDs up to 6 in your table and you deleted ID 2, would you want the next input to be an ID of 2? That doesn't seem to follow the ACID properties. Also, if there was a dependence on that data, for example, if it was user data, and the ID determined user IDs, it would invalidate pre-existing information, since if user X was deleted and the same ID was assigned to user Y, that could cause integrity issues in dependent systems.
Also, imagine a table with 50 billion rows. Should the table run an O(n) search for the smallest missing ID every time you're trying to insert a new record? I can see that getting out of hand really quickly.
Some links you might like to read:
Principles of Transaction-Oriented Database Recovery (1983)
How can we re-use the deleted id from any MySQL-DB table?
Why do you care?
Primary keys are internal row identifiers that are not supposed to be sexy or good looking. As long as they are able identify each row uniquely, they serve their purpose.
Now, if you care about its value, then you probably want to expose the primary key value somewhere, and that's a big red flag. If you need an external, visible identifier, you can create a secondary column with any formatting sequence and values you want.
As a side note, the term AUTO_INCREMENT is a bit misleading. It doesn't really mean they increase one by one all the time. It just mean it will try to produce sequential numbers, as long as it is possible. In multi-threaded apps that's usually not possible since batches or numbers are reserved per thread so the row insertion sequence may end actually not following the natural numbering. Row deletions have a similar effect, as well as INSERT with roll backs.
Primary keys are meant to be used for joining tables together and
indexing, they are not meant to be used for human usage. Reordering
primary key columns could orphan data and wreck havoc to your queries.
Tips: Add another column to your table and reorder that column to your will if needed (show that column to your user instead of the primary key).

Should I use my two columns that uniquely identify a record as primary key?

I started to design a database that tracks system events by following some online tutorials, and some easy examples start by assigning auto-incrementing IDs as primary keys. I looked at my database, I don't really need IDs. Out of all my columns, the timestamp and device ID are the two columns that together identifies an unique event.
What my program does right now is to pull some events from system log in the past x minutes and insert these events to the database. However, I could be going too much into the past that the events overlap with what's already in the database. As I mentioned before, timestamp and device ID are the two fields that uniquely identify an event. My question is, should I use these two fields as my primary key and use "Insert ignore" from now on so I can avoid having duplicate records?
It is a good practise to never have your business values as table's primary key and always to use synthetic, e.g. autoincrement, values for this. You will make your life easier in the future when business requirements change :)
We are currently struggling with exactly this situation. Have a column with business values as a primary key for 2 years and now painfully introducing an autoincrement one.
You may need to use foreign key from other table to this in the future to link some rows between two tables. It is easier with one-column primary key.
But if you don't need it now - no need to create column special for index. Table can be altered in future to add such column with autoincrement and move primary key to it.

Renewable primary or unique key

There is a table. No PK, 2 FK, with some arbitrary number of columns.
Unfortunately FK are not unique in any way.
Adding new data is easy.
Deleting data (finding a row) is ok if I put unique constraint to some other col.
(DELETE ... WHERE fk1=:fk1 AND fk2=:fk2 AND ucol=:ucol)
What to do with UPDATE?
I cant use that ucol because that same ucol might be subject of change. I have several solutions, but none of them seem ok.
Solution1:
Put PK in table. Use it for DELETE and UPDATE. Deleting will make lot of holes in it but that's no problem. In theory, it can run out of PK numbers (int, unsigned int) if there's some heavy deleting going on.
Solution1a
Make CK of (fk1, fk2, some new col) use that to locate the row. It's the same as just using the PK.
Solution2
Use timestamp with microtime/ hash/ unique key generator/ something to populate new unique col. That col is used as PK to locate the row for UPDATE and DELETE. Excellent only if unique algo does it's job perfectly.
My question:
Is there something better? That doesn't require fancy algorithms and have no risk of overflowing auto-incremented PK...
----------------- edit----------------
Solution2a
Use mysql UUID! It's far better (and easier to use) than, creating custom timestamp / hash / something_unique.
As per my suggestion , it will be better to add a PK to the table because of following reasons:
1. It will give unique id to each row , which will help in DELETE and UPDATE script.
2. PK will create a cluster index on the column which will improve performace of the table while retriving data.
3. Its always adviced to provide a PK in each table.
4. In future you can use the PK as a FK in any table if required.

MySQL: Insert a new row at a specific primary key, or alternately, bump all subsequent rows down?

I am creating two tables in a database in MySQL just so I can play around with SQL and learn more, as I am a novice. I have read several questions on Stack relating to inserting a new row, and updating an existing row. My question is a little different, hopefully it won't be considered a dupe as none of the other answers I read gave me the full explanation I need because I think it's the auto-increment part that's confusing me. I don't think I can just go in and assign a new value for the primary keys in one of the tables with auto-increment set up, can I?
I have two tables: english_words and spanish_words. Their primary keys are respectively eng_id and span_id, and are set up to auto-increment. My hope had been to practice SQL and eventually get things set up enough so that I can practice my joins later on. For now, in english_words, I entered a duplicate row by mistake, with the ID 7. I deleted that row, and of course it now goes "6...8..." ..... and when I created my spanish_words table, I forgot all about the missing row 7. I'd hoped to keep everything very simple and aligned between the two tables until I'm ready for more complex endeavors later. Is there a way I can either:
Bump row 7 (and all subsequent rows) down by one in my spanish_words (so 7 becomes 8, 8 becomes 9, etc)
OR
Pull up everything after row 6 in english_words?
OR
Is there a better solution than either of those that you could suggest?
It's possible there's not a way. Originally I'd thought of trying to UPDATE the row 7 data in english_words or maybe insert a new row, but in my research I found an answer on Stack that said you can't insert data into a specific row in the table...and then I realized that's not going to fix anything anyway.
Do those of you more experienced with SQL have any ideas? (Aside from not making such silly mistakes anyway).
Additionally, I'm open to scrapping my tables and starting again, if there's a best-practice that I'm missing. Would setting up a foreign key to correspond between the two tables be a way to fix this? I'm pretty sure you have to do that anyway to perform the joins, but I was going to cross that bridge when I get there. What is best practice amongst database admins - set up foreign keys early on, or later when you need them?
Thanks in advance for your guidance.
A better way to set this up is to create a relation table:
CREATE TABLE translation (
eng_id int,
span_id int,
FOREIGN KEY (eng_id) REFERENCES english_words (eng_id),
FOREIGN KEY (span_id) REFERENCES spanish_words (span_id)
)
This is better than using a foreign key in the original tables, because you can't have bidirection foreign keys (you have to create the referenced row before the referencing row, so whichever table you insert into first can't have a foreign key pointing to the other one).

How to properly deal with long key constraints(longer than 3072) in MySql?

I can see that there are similar questions and answers on SO regarding this problem.
I need to create a unique constraint on 7 columns together.
alter table ga_data_model add constraint uq_1234596 unique (portal_id,date,dimension,country,os,os_version,theme);
there has been various answers to use prefix keys to solve this issue. However, because of the nature of my data, simply using the first one or two character to create the index is dangerous as this might result in having duplicate results. So such a solution won't work for me:
alter table ga_data_model add constraint uq_1234596 unique (portal_id,date(2),dimension(2),country(1),os(2),os_version(1),theme(2));
I was thinking of creating a new column in my table that contains the calculated hash of these columns and I create my constraint on this one. But this means that every time I want to insert something into db, I need to first do a select for this column, calculated the hash for the new values, compare them and save/or not save. I think this is a bit too expensive, considering that I will be having a lot of write operations.
Has anyone had the same problem and have a better solution as I explained above?
Thanks!
I want to insert something into db, I need to first do a select for this column, calculated the hash for the new values, compare them and save/or not save
No - you save it, and if you get a unique key violation then you already have the data. Also, implement the hash calculation as a table trigger - that way there's no backdoor for amending the data.