MySQL read only transaction can modify table - mysql

I'm trying to use read only transaction in MySQL and I'm confused how it can modify (insert to table ) and can alter table column ( DDL and DML). example :
SET ##transaction_read_only=true;
start transaction ;
insert into Table_NAME (ID,name) values (3,'test');
ALTER TABLE Table_Name MODIFY COLUMN name VARCHAR (1000);
commit ;
can anybody explain what is wrong here ?
Update: I'm using datagrip and I found the issue is with DataGrip from mysql shell this doesn't work : insert into Table_NAME (ID,name) values (3,'test');
however this still work :
ALTER TABLE Table_Name MODIFY COLUMN name VARCHAR (1000);

ALTER TABLE will cause an implicit commit, so that that will be another transaction.
Don't put DDL in the transaction, it will make things complicated.
SET ##transaction_read_only=true; only works for the next transaction; while SET ##session.transaction_read_only = true is for the session.

Related

Records get deleted from a specific table, leaving exactly the same amount of records (54) left each time

Okay, I've just inherited a project from a previous developer, before I came in they had problems of a particular table losing records and leaving exactly the same number of records each time, the records get erased completely. And I noticed that there are lots of DELETE statements in the code as well, but I can't find the script that deletes the records.
For now I run a CRON job twice a day to back up the database.
I have checked for CASCADE DELETE using this SQL
USE information_schema;
SELECT
table_name
FROM
referential_constraints
WHERE
constraint_schema = 'my_database_name'
AND referenced_table_name IN
(SELECT table_name
FROM information_schema.tables
WHERE table_schema ='my_database_name')
AND delete_rule = 'CASCADE'
It lists all the tables in my database and checks for any possibilities of a CASCADE DELETE, but so far it returns empty.
I use SQL a lot because I'm a back-end developer but I'm not an expert at it. So I could really use some help because it's getting quite embarrassing each time it happens. It's a MySQL database. Thanks.
I onced faced a similar situation. I created an SQL TRIGGER statement that stored the rows into another table before they get deleted, that way:
I was able to restore the lost data each time it happened.
I was able to study the rows being deleted and the information helped in resolving the situation.
Here's a sample for backing up the records before they are deleted:
CREATE TABLE `history_table` LIKE `table`;
ALTER TABLE `history_table`
MODIFY COLUMN `id` INT UNSIGNED NOT NULL;
ALTER TABLE `history_table` DROP PRIMARY KEY;
DELIMITER $$
CREATE TRIGGER `deleted_table` BEFORE DELETE on `table`
FOR EACH ROW
BEGIN
INSERT INTO history_table
SELECT *
FROM table
WHERE id = OLD.id;
END$$
DELIMITER ;
For restoring the table
INSERT INTO table
SELECT * FROM history_table

How to use IF EXISTS to check whether table exists before removing data in that table

I wanted to check whether a table exists before deleting the values inside the table. In SQL Server we can do as simple as so :
IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'table_to_be_edited')
BEGIN
DELETE FROM table_to_be_edited;
END;
but how do we do it in MySQL ?
I am using MySQL Workbench V8.0.
When delete an option is to ignore the table not found error. This eliminates race conditions where a table is created between the test and the truncate. Always consider this when doing SQL operations.

MySql Query to Update Auto increment Primary Key [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.

Copying Tables Without Data in MySQL Retaining Auto Increment

I have ran into trouble when copying my MySQL Tables to a new one, excluding the data, using the query:
CREATE TABLE foo SELECT * FROM bar WHERE 1=0.
The tables are copied, the structure and column names are correctly inserted. But there is a problem with the auto_increment fields and the primary key fields as they are not inserted as they were on the original table. (The fields are not PKs and AI anymore) I am using MySQL 5.5 and PMA 3.5.8.2
I hope someone can help me out.
Thank you SO.
You will probably have to run 2 queries.
CREATE TABLE foo LIKE bar;
ALTER TABLE foo AUTO_INCREMENT = (SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'DatabaseName' AND TABLE_NAME = 'bar');
You would have to replace DatabaseName with the name of your database. This is untested, but I think it will give you what you are looking for.
So I tried testing the above query and the ALTER TABLE statement seems to fail due to the select. There might be a better way, but the way that worked for me was to set the auto increment value to a variable and then prepare the statement and execute it.
For example you would go ahead and create your table first:
CREATE TABLE foo LIKE bar;
Then set your ALTER TABLE statement into a variable
SET #ai = CONCAT("ALTER TABLE foo AUTO_INCREMENT =", (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'databasename' AND TABLE_NAME = 'bar'));
Finally, you would prepare and execute the statement.
PREPARE query FROM #ai;
EXECUTE query;
DEALLOCATE PREPARE query;
Other than your columns, the table structure: indexes, primary keys, triggers, etc. are not copied by this kind of statement. You either need to run a bunch of alter table statements to add your structure or you need to create the table with all the surrounding structure first, then load it with your select.

How to reset AUTO_INCREMENT in MySQL

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.