INSERT VALUES into empty column - mysql

$querychange =
mysql_query("UPDATE table SET clounm='$newvale' WHERE email='$email'")
but put $newvalue into the nearest empty cell

Consider the following code:
UPDATE `table_name` SET `col_name` = `col_value` WHERE `record_name` = 'ID'
for example
UPDATE `student` SET `marks` = 50 WHERE `name` = 'Jack'
This will set all records with name Jack to 50 marks.

Is this what your looking for
UPDATE table SET clounm='$newvale' WHERE email IS NULL LIMIT 1

Related

update a table after inserting a value in the same table using triggers [duplicate]

I am running a MySQL Query. But when a new row is added from form input I get this error:
Error: Can't update table 'brandnames' in stored function/trigger because it is
already used by statement which invoked this stored function/trigger.
From the code:
CREATE TRIGGER `capital` AFTER INSERT ON `brandnames`
FOR EACH
ROW UPDATE brandnames
SET bname = CONCAT( UCASE( LEFT( bname, 1 ) ) , LCASE( SUBSTRING( bname, 2 ) ) )
What does this error mean?
You cannot change a table while the INSERT trigger is firing. The INSERT might do some locking which could result in a deadlock. Also, updating the table from a trigger would then cause the same trigger to fire again in an infinite recursive loop. Both of these reasons are why MySQL prevents you from doing this.
However, depending on what you're trying to achieve, you can access the new values by using NEW.fieldname or even the old values --if doing an UPDATE-- with OLD.
If you had a row named full_brand_name and you wanted to use the first two letters as a short name in the field small_name you could use:
CREATE TRIGGER `capital` BEFORE INSERT ON `brandnames`
FOR EACH ROW BEGIN
SET NEW.short_name = CONCAT(UCASE(LEFT(NEW.full_name,1)) , LCASE(SUBSTRING(NEW.full_name,2)))
END
The correct syntax is:
FOR EACH ROW SET NEW.bname = CONCAT( UCASE( LEFT( NEW.bname, 1 ) )
, LCASE( SUBSTRING( NEW.bname, 2 ) ) )
A "BEFORE-INSERT"-trigger is the only way to realize same-table updates on an insert, and is only possible from MySQL 5.5+. However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case. Therefore the following example code which would set a previously-calculated surrogate key value based on the auto-increment value id will compile, but not actually work since NEW.id will always be 0:
create table products(id int not null auto_increment, surrogatekey varchar(10), description text);
create trigger trgProductSurrogatekey before insert on product
for each row set NEW.surrogatekey =
(select surrogatekey from surrogatekeys where id = NEW.id);
#gerrit_hoekstra wrote: "However, the value of an auto-increment field is only available to an "AFTER-INSERT" trigger - it defaults to 0 in the BEFORE-case."
That is correct but you can select the auto-increment field value that will be inserted by the subsequent INSERT quite easily. This is an example that works:
CREATE DEFINER = CURRENT_USER TRIGGER `lgffin`.`variable_BEFORE_INSERT` BEFORE INSERT
ON `variable` FOR EACH ROW
BEGIN
SET NEW.prefixed_id = CONCAT(NEW.fixed_variable, (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'lgffin'
AND TABLE_NAME = 'variable'));
END
I have the same problem and fix by add "new." before the field is updated. And I post full trigger here for someone to want to write a trigger
DELIMITER $$
USE `nc`$$
CREATE
TRIGGER `nhachung_province_count_update` BEFORE UPDATE ON `nhachung`
FOR EACH ROW BEGIN
DECLARE slug_province VARCHAR(128);
DECLARE slug_district VARCHAR(128);
IF old.status!=new.status THEN /* neu doi status */
IF new.status="Y" THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
ELSE
UPDATE province SET `count`=`count`-1 WHERE id = new.district_id;
END IF;
ELSEIF old.province_id!=new.province_id THEN /* neu doi province_id + district_id */
UPDATE province SET `count`=`count`+1 WHERE id = new.province_id; /* province_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.province_id;
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id; /* district_id */
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
ELSEIF old.district_id!=new.district_id THEN
UPDATE province SET `count`=`count`+1 WHERE id = new.district_id;
UPDATE province SET `count`=`count`-1 WHERE id = old.district_id;
SET slug_province = ( SELECT slug FROM province WHERE id= new.province_id LIMIT 0,1 );
SET slug_district = ( SELECT slug FROM province WHERE id= new.district_id LIMIT 0,1 );
SET new.prov_dist_url=CONCAT(slug_province, "/", slug_district);
END IF;
END;
$$
DELIMITER ;
Hope this help someone

Subtracting a value directly in sql table [duplicate]

I would like decrease by 1 the value contained inside a field (integer or drop-down). I tried these 3 queries but none of them work as expected:
UPDATE `my_table` SET `my_field` = 'my_field-1' WHERE `other` = '123'
UPDATE `my_table` SET `my_field` = 'my_field' -1 WHERE `other` = '123'
UPDATE `my_table` SET `my_field` = '-1' WHERE `other` = '123'
I searched here and on Google but all solutions I found are similar. Any idea why this doesn't work at my side?
You don't need any quotes.
UPDATE my_table SET my_field = my_field - 1 WHERE `other` = '123'
To understand, it's like a classic affectation in any languages: "I want my_field being equal to my_field (the current value) minus 1.
If you put quotes, it means "I want my_field being equal to the string:
'my_field-1' (for your first query)
'my_field' - 1 (which means nothing, at least for me: what the result of a string minus an integer?)
'-1', which will be converted to -1 if your field has the INTEGER signed type.
In some cases (if you have spaces or special characters if your field name), you can surrounded the field name with `backticks`:
UPDATE my_table SET `my_field` = `my_field` - 1 WHERE other = '123'
Try this one remove single quotes from the column name other it will be treated as string 'my_field-1' or use back-ticks around column name
UPDATE my_table SET my_field = my_field - 1 WHERE `other` = '123'
or
UPDATE my_table SET `my_field` = `my_field` - 1 WHERE `other` = '123'

MySql WHERE condition based on unique index

I have the following table groupToScore:
CREATE TABLE `groupToScore` (
`groupId` int NOT NULL,
`scoreId` varchar(255) NOT NULL,
`scoreName` varchar(255) DEFAULT NULL,
UNIQUE KEY `gToS` (`groupId`,`scoreId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
The pair (groupId, scoreId) form a unique key gTos for this table.
My question is how do I perform UPDATE using gTos in the WHERE clause?
It would look something like, UPDATE groupToScore SET scoreName = #{scoreName} WHERE gToS is equal to (groupId, scoreId).
UPDATE groupToScore SET scoreName = #{scoreName} WHERE groupId = 1 and scoreId = 1;
I believe mysql server will choose a proper index for you and you can get the one sql indexing information by put a explain at the top of the sql
explain UPDATE groupToScore SET scoreName = #{scoreName} WHERE groupId = 1 and scoreId = 1;
You can't use indices directly. The SQL engine uses the index automatically if it is applicable. Therefore, you simply query for WHERE groupId = ? AND scoreId = ?.
You cannot use the key name directly but you can use its expression. Try this:
UPDATE groupToScore SET scoreName = #{scoreName} WHERE (`groupId`,`scoreId`) = (groupId, scoreId)
--e.g for a single match
insert groupToScore values(1,3,'dd'),(1,2,'xx');
UPDATE groupToScore SET scoreName = 'aa' WHERE (`groupId`,`scoreId`) = (1, 2);
--e.g for multiple matches
UPDATE groupToScore SET scoreName = 'kk' WHERE (`groupId`,`scoreId`) in (
(1,2),
(1,3)
);
groupId = 1 and scoreId = 1
will fail to fully use your
UNIQUE KEY `gToS` (`groupId`,`scoreId`)
because of a type conflict.
When comparing a varchar column to an integer literal, the column is converted to an integer before performing the test. Do, instead
groupId = 1 and scoreId = "1"
It does not matter if you have groupId = "1"; the string will be converted to a number and the index can still be used.
The update is simply
UPDATE groupToScore SET
scoreName = #{scoreName}
WHERE groupId = 123, scoreId = "987"
And/or, change the datatype of `scoreId to be something numeric. (Of course, this assumes its values are really numbers.

MySQL: Deleted a tuple (which had an ID of 10), and when I add a new entry, the ID is 11, not 10 [duplicate]

I have a MySQL table with an auto increment primary key. I deleted some rows in the middle of the table. Now I have, for example, something like this in the ID column: 12, 13, 14, 19, 20. I deleted the 15, 16, 17 and 18 rows.
I want to reassign / reset / reorder the primary key so that I have continuity, i.e. make the 19 a 15, the 20 a 16, and so on.
How can I do it?
Even though this question seems to be quite old, will post an answer for someone who reaches in here searching.
SET #count = 0;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
If the column is used as a foreign key in other tables, make sure you use ON UPDATE CASCADE instead of the default ON UPDATE NO ACTION for the foreign key relationship in those tables.
Further, in order to reset the AUTO_INCREMENT count, you can immediately issue the following statement.
ALTER TABLE `users` AUTO_INCREMENT = 1;
For MySQLs it will reset the value to MAX(id) + 1.
You could drop the primary key column and re-create it. All the ids should then be reassigned in order.
However this is probably a bad idea in most situations. If you have other tables that have foreign keys to this table then it will definitely not work.
To reset the IDs of my User table, I use the following SQL query. It's been said above that this will ruin any relationships you may have with any other tables.
ALTER TABLE `users` DROP `id`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
You may simply use this query
alter table abc auto_increment = 1;
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
I think this will do it
Or, from PhpMyAdmin, remove "AutoIncrement" flag, save, set it again and save.this resets it.
SELECT * from `user` ORDER BY `user_id`;
SET #count = 0;
UPDATE `user` SET `user_id` = #count:= #count + 1;
ALTER TABLE `user_id` AUTO_INCREMENT = 1;
if you want to order by
in phpmyadmin
note: this will work if you delete last rows not middle rows.
goto your table-> click on operations menu-> goto table options->change AUTO_INCREMENT to that no from where you want to start.
your table autoincrement start from that no.
try it.
This works - https://stackoverflow.com/a/5437720/10219008.....but if you run into an issue 'Error Code: 1265. Data truncated for column 'id' at row 1'...Then run the following. Adding ignore on the update query.
SET #count = 0;
set sql_mode = 'STRICT_ALL_TABLES';
UPDATE IGNORE web_keyword SET id = #count := (#count+1);
I had the same doubts, but could not make any changes on the table, I decided doing the following having seen my ID did not exceed the maximum number setted in the variable #count:
SET #count = 40000000;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
SET #count = 0;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
ALTER TABLE `users` AUTO_INCREMENT = 1;
The solution takes, but it's safe and it was necessary because my table owned foreign keys with data in another table.
You can remove the primary key auto increment functionality of that column, then every time you update that column run a query before hand that will count all the rows in the table, then run a loop that iterates through that row count inserting each value into the respective row, and finally run a query inserting a new row with the value of that column being the total row count plus one. This will work flawlessly and is the most absolute solution to someone trying to accomplish what you are. Here is an example of code you may use for the function:
$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("
SELECT `rank`, `field1`, `field2`, `field3`, `field4`
FROM (SELECT (#rank:=#rank+1) as `rank`, `field1`, `field2`, `field3`, `field4`
FROM (SELECT * FROM `views`) a
CROSS JOIN (SELECT #rank:=0) b
ORDER BY rank ASC) c
");
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
$data[] = $row;
}
foreach ($data as $row) {
$new_field_1 = (int)$row['rank'];
$old_field_1 = (int)$row['field1'];
mysql_query("UPDATE `table` SET `field_1` = $new_field_1 WHERE `field_1` = $old_field_1");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");
Here I created an associative array which I had appended on a rank column with the query within a select query, which gave each row a rank value starting with 1. I then iterated through the associative array.
Another option would have been to get the row count, run a basic select query, get the associative array and iterate it through the same way but with an added variable that updates through each iteration. This is less flexible but will accomplish the same thing.
$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("SELECT * FROM `table`");
$updated_key = 0;
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
$data[] = $row;
}
foreach ($data as $row) {
$updated_key = $updated_key + 1;
mysql_query("UPDATE `table` SET `field_1` = '$updated_key' WHERE `field_1` = '$row['field_1']'");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");
for InnoDB, do this (this will remove all records from a table, make a bakcup first):
SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS ;
SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION ;
SET NAMES utf8 ;
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0 ;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ;
SET #OLD_SQL_NOTES=##SQL_NOTES, SQL_NOTES=0 ;
/* ================================================= */
drop table tablename;
CREATE TABLE `tablename` (
table structure here!
) ENGINE=InnoDB AUTO_INCREMENT= ai number to reset DEFAULT CHARSET= char set here;
/* ================================================= */
SET SQL_MODE=#OLD_SQL_MODE ;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS ;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS ;
SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT ;
SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS ;
SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION ;
SET SQL_NOTES=#OLD_SQL_NOTES ;
The best choice is to alter the column and remove the auto_increment attribute. Then issue another alter statement and put auto_increment back onto the column. This will reset the count to the max+1 of the current rows and thus preserve foreign key references back to this table, from other tables in your database, or any other key usage for that column.
My opinion is to create a new column called row_order. then reorder that column. I'm not accepting the changes to the primary key. As an example, if the order column is banner_position, I have done something like this, This is for deleting, updating, creating of banner position column. Call this function reorder them respectively.
public function updatePositions(){
$offers = Offer::select('banner_position')->orderBy('banner_position')->get();
$offersCount = Offer::max('banner_position');
$range = range(1, $offersCount);
$existingBannerPositions = [];
foreach($offers as $offer){
$existingBannerPositions[] = $offer->banner_position;
}
sort($existingBannerPositions);
foreach($existingBannerPositions as $key => $position){
$numbersLessThanPosition = range(1,$position);
$freshNumbersLessThanPosition = array_diff($numbersLessThanPosition, $existingBannerPositions);
if(count($freshNumbersLessThanPosition)>0) {
$existingBannerPositions[$key] = current($freshNumbersLessThanPosition);
Offer::where('banner_position',$position)->update(array('banner_position'=> current($freshNumbersLessThanPosition)));
}
}
}
Delete your id column and execute ALTER TABLE table_name ADD COLUMN id INT NOT NULL AUTO_INCREMENT UNIQUE;
You can also simply avoid using numeric IDs as Primary Key. You could use Country codes as primary id if the table holds countries information, or you could use permalinks, if it hold articles for example.
You could also simply use a random, or an MD5 value. All this options have it's own benefits, specially on IT sec. numeric IDs are easy to enumerate.

Reorder / reset auto increment primary key

I have a MySQL table with an auto increment primary key. I deleted some rows in the middle of the table. Now I have, for example, something like this in the ID column: 12, 13, 14, 19, 20. I deleted the 15, 16, 17 and 18 rows.
I want to reassign / reset / reorder the primary key so that I have continuity, i.e. make the 19 a 15, the 20 a 16, and so on.
How can I do it?
Even though this question seems to be quite old, will post an answer for someone who reaches in here searching.
SET #count = 0;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
If the column is used as a foreign key in other tables, make sure you use ON UPDATE CASCADE instead of the default ON UPDATE NO ACTION for the foreign key relationship in those tables.
Further, in order to reset the AUTO_INCREMENT count, you can immediately issue the following statement.
ALTER TABLE `users` AUTO_INCREMENT = 1;
For MySQLs it will reset the value to MAX(id) + 1.
You could drop the primary key column and re-create it. All the ids should then be reassigned in order.
However this is probably a bad idea in most situations. If you have other tables that have foreign keys to this table then it will definitely not work.
To reset the IDs of my User table, I use the following SQL query. It's been said above that this will ruin any relationships you may have with any other tables.
ALTER TABLE `users` DROP `id`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
You may simply use this query
alter table abc auto_increment = 1;
SET #num := 0;
UPDATE your_table SET id = #num := (#num+1);
ALTER TABLE your_table AUTO_INCREMENT =1;
I think this will do it
Or, from PhpMyAdmin, remove "AutoIncrement" flag, save, set it again and save.this resets it.
SELECT * from `user` ORDER BY `user_id`;
SET #count = 0;
UPDATE `user` SET `user_id` = #count:= #count + 1;
ALTER TABLE `user_id` AUTO_INCREMENT = 1;
if you want to order by
in phpmyadmin
note: this will work if you delete last rows not middle rows.
goto your table-> click on operations menu-> goto table options->change AUTO_INCREMENT to that no from where you want to start.
your table autoincrement start from that no.
try it.
This works - https://stackoverflow.com/a/5437720/10219008.....but if you run into an issue 'Error Code: 1265. Data truncated for column 'id' at row 1'...Then run the following. Adding ignore on the update query.
SET #count = 0;
set sql_mode = 'STRICT_ALL_TABLES';
UPDATE IGNORE web_keyword SET id = #count := (#count+1);
I had the same doubts, but could not make any changes on the table, I decided doing the following having seen my ID did not exceed the maximum number setted in the variable #count:
SET #count = 40000000;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
SET #count = 0;
UPDATE `users` SET `users`.`id` = #count:= #count + 1;
ALTER TABLE `users` AUTO_INCREMENT = 1;
The solution takes, but it's safe and it was necessary because my table owned foreign keys with data in another table.
You can remove the primary key auto increment functionality of that column, then every time you update that column run a query before hand that will count all the rows in the table, then run a loop that iterates through that row count inserting each value into the respective row, and finally run a query inserting a new row with the value of that column being the total row count plus one. This will work flawlessly and is the most absolute solution to someone trying to accomplish what you are. Here is an example of code you may use for the function:
$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("
SELECT `rank`, `field1`, `field2`, `field3`, `field4`
FROM (SELECT (#rank:=#rank+1) as `rank`, `field1`, `field2`, `field3`, `field4`
FROM (SELECT * FROM `views`) a
CROSS JOIN (SELECT #rank:=0) b
ORDER BY rank ASC) c
");
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
$data[] = $row;
}
foreach ($data as $row) {
$new_field_1 = (int)$row['rank'];
$old_field_1 = (int)$row['field1'];
mysql_query("UPDATE `table` SET `field_1` = $new_field_1 WHERE `field_1` = $old_field_1");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");
Here I created an associative array which I had appended on a rank column with the query within a select query, which gave each row a rank value starting with 1. I then iterated through the associative array.
Another option would have been to get the row count, run a basic select query, get the associative array and iterate it through the same way but with an added variable that updates through each iteration. This is less flexible but will accomplish the same thing.
$table_row_count = mysql_result(mysql_query("SELECT COUNT(`field_1`) FROM `table`"), 0);
$viewsrowsdata = mysql_query("SELECT * FROM `table`");
$updated_key = 0;
while ($row = mysql_fetch_assoc($viewsrowsdata)) {
$data[] = $row;
}
foreach ($data as $row) {
$updated_key = $updated_key + 1;
mysql_query("UPDATE `table` SET `field_1` = '$updated_key' WHERE `field_1` = '$row['field_1']'");
}
mysql_query("INSERT INTO `table` (`field1`, `field2`, `field3`, `field4`) VALUES ('$table_row_count' + 1, '$field_2_value', 'field_3_value', 'field_4_value')");
for InnoDB, do this (this will remove all records from a table, make a bakcup first):
SET #OLD_CHARACTER_SET_RESULTS=##CHARACTER_SET_RESULTS ;
SET #OLD_COLLATION_CONNECTION=##COLLATION_CONNECTION ;
SET NAMES utf8 ;
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0 ;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 ;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' ;
SET #OLD_SQL_NOTES=##SQL_NOTES, SQL_NOTES=0 ;
/* ================================================= */
drop table tablename;
CREATE TABLE `tablename` (
table structure here!
) ENGINE=InnoDB AUTO_INCREMENT= ai number to reset DEFAULT CHARSET= char set here;
/* ================================================= */
SET SQL_MODE=#OLD_SQL_MODE ;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS ;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS ;
SET CHARACTER_SET_CLIENT=#OLD_CHARACTER_SET_CLIENT ;
SET CHARACTER_SET_RESULTS=#OLD_CHARACTER_SET_RESULTS ;
SET COLLATION_CONNECTION=#OLD_COLLATION_CONNECTION ;
SET SQL_NOTES=#OLD_SQL_NOTES ;
The best choice is to alter the column and remove the auto_increment attribute. Then issue another alter statement and put auto_increment back onto the column. This will reset the count to the max+1 of the current rows and thus preserve foreign key references back to this table, from other tables in your database, or any other key usage for that column.
My opinion is to create a new column called row_order. then reorder that column. I'm not accepting the changes to the primary key. As an example, if the order column is banner_position, I have done something like this, This is for deleting, updating, creating of banner position column. Call this function reorder them respectively.
public function updatePositions(){
$offers = Offer::select('banner_position')->orderBy('banner_position')->get();
$offersCount = Offer::max('banner_position');
$range = range(1, $offersCount);
$existingBannerPositions = [];
foreach($offers as $offer){
$existingBannerPositions[] = $offer->banner_position;
}
sort($existingBannerPositions);
foreach($existingBannerPositions as $key => $position){
$numbersLessThanPosition = range(1,$position);
$freshNumbersLessThanPosition = array_diff($numbersLessThanPosition, $existingBannerPositions);
if(count($freshNumbersLessThanPosition)>0) {
$existingBannerPositions[$key] = current($freshNumbersLessThanPosition);
Offer::where('banner_position',$position)->update(array('banner_position'=> current($freshNumbersLessThanPosition)));
}
}
}
Delete your id column and execute ALTER TABLE table_name ADD COLUMN id INT NOT NULL AUTO_INCREMENT UNIQUE;
You can also simply avoid using numeric IDs as Primary Key. You could use Country codes as primary id if the table holds countries information, or you could use permalinks, if it hold articles for example.
You could also simply use a random, or an MD5 value. All this options have it's own benefits, specially on IT sec. numeric IDs are easy to enumerate.