Stored Procedure to read text file and loop through it - mysql

I tried looking through a lot of threads on this but couldn't find anything that works for me.
I have a text file with list of table names (about 100 out of 300 total tables in the schema).
tables.txt
table1
table2
table3
I am writing a stored procedure and want to loop through the table names in that text file and inject the table names in the query.
Something like this
While (line = readline) != null do
update line set col1='foo' where id=x;
End while;
Is something like that even possible in a stored procedure? using (mysql 5.6). and I am using Workbench 6.3 CE

Since you want to run the same code for every table in your database.You can create your command using Information Schema
USE INFORMATION_SCHEMA;
SELECT
CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` ALTERING CODE HERE;")
AS MySQLCMD FROM TABLES
WHERE TABLE_SCHEMA = "your_schema_goes_here";
When the commands are created then you can copy and run all of them.
UPDATE If you want to update a column common between all those tables you can write it as follow
SELECT CONCAT("UPDATE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` SET COLUMN_NAME = VALUE [ANY WHERE CLAUSE]") as MySQLCMD from TABLES where TABLE_SCHEMA = "YourSchemaName";
UPDATE2 Generating commands for specific tables.
SELECT
CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` ALTERING CODE HERE;")
AS MySQLCMD FROM TABLES
WHERE TABLE_SCHEMA = "your_schema_goes_here" AND TABLE_NAME IN ('Table1', 'TAble2');

In general I would take this approach. There is not enough detail to be more specific. Note, this uses dynamic SQL rather than a stored procedure.
Backup your database!!
Create a temporary table. (either real or in memory depending on how long you need this data retained)
Parse the text file into a temporary table using something like this:
LOAD DATA INFILE '/tmp/mylist.txt' INTO TABLE MyTempList;
Create a test a single ALTER table statement. Once you know it works exactly as intended...
Convert your working ALTER statement into dynamic SQL that selects the table names from your temporary table. Something like this: Alter table using sub select
When complete, you can delete your temporary table.
Alternately, you could put a single ALTER statement into a stored procedure, asking for the table name as a parameter. But then you will still need to parse the text file using something like steps 1-3. And then use a cursor to loop over the table names and call the stored procedure.

Related

Change all columns of tables containing some characters

In MySQL, how to change all columns names of all tables to remove the string "_euro" from columns names?
I just could find a way to search tables having some columns containing "_euro" in their names:
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE "%_euro"
AND TABLE_SCHEMA='my_database'
For example, for the column named price_total_euro I want to rename it as price_total
Create a script with the following SQL:
SELECT CONCAT("ALTER TABLE ",TABLE_SCHEMA,".",TABLE_NAME," RENAME COLUMN ",COLUMN_NAME," TO ",REPLACE(COLUMN_NAME,"_euro",""),"; ")
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE "%_euro"
output will be, multiple lines which look like this:
ALTER TABLE test.t1_euro RENAME COLUMN t1_euro TO t1;
Review the script, and execute it on your database (after making a backup....)
put your select into a stored procedure and make a cursor and loop on all and do the alter operation
you can find example for a procedure here : https://stackoverflow.com/questions/15786240/mysql-create-stored-procedure-syntax-with-delimiter#:~:text=Getting%20started%20with%20stored%20procedure%20syntax%20in%20MySQL%3A,Why%20didn%27t%20this%20work%3F%20...%20More%20items...%20
if your using python with MySQL Connector you could place the column headers into a list and then run it through a for loop?
for name in table_names:
if name.endswith("_euro"):
new_name = name.replace("_euro", "")

MySQl Bulk Rename, Alter , Update

I have a MySQl database with more than 200 tables. I want to do following on ALL tables in this database.
Update all table name by adding a constant to the name
Add column (Alter table) to each table
Update each table to set newly added column
Can someone please suggest an efficient way of doing this
Thanks
bhim
You need to write a couple of SQL statements that will generate the rename / add column SQL statements.
Then you can run the SQL Statements.
You haven't provided table names, or schemas, etc. so I can give guidance but not exact results.
So assuming your "adding a constant to the name" is prefixing "const_" to it, you could do something like:
SELECT 'RENAME TABLE ''' || table_name || ''' TO ''const_' || table_name || ''' FROM information_schema.tables WHERE table_catalog = 'YourCatalog' and table_schema = 'YourSchema';
This would give you the rename table command as the output, which you could pick up and put in a text editor to tidy up.
You'll need to execute a few queries against INFORMATION_SCHEMA.tables to figure out the right filter to get the right criteria for the tables list.
And you can do similar for the Add column statement.
Some useful references:
Information schema: https://dev.mysql.com/doc/refman/5.7/en/tables-table.html
Rename a table: https://blog.marceloaltmann.com/en-how-to-rename-table-in-mysql-pt-como-renomear-tabelas-no-mysql/
Add a column: http://www.mysqltutorial.org/mysql-add-column/

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 would I delete a single column in all tables in MYSQL

I have a column 'seq' in every table of my database that I would like to delete easily.
I have to do this on occasion in MySQL and am hoping this can be automated.
There isn't a simple magical expression to just do this. You need to generate a list of SQL statements and then run them, somehow.
(Most database folks don't routinely drop columns from a database in production; it takes a lot of time during which the tables are inaccessible, and it's destructive. A fat-finger error could really mess you up.)
You might start by using the information_schema in MySQL to discover which of your tables have a seq column in them. This query will return that list of tables for the database you're currently using.
SELECT DISTINCT TABLE_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME = 'seq'
You could then adapt that query to, for example, create a list of statements like this.
SELECT DISTINCT
CONCAT('UPDATE ',TABLE_NAME, ' SET seq = 0;') AS stmt
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND COLUMN_NAME = 'seq'
This will produce a result set like this:
UPDATE table_a SET seq = 0;
UPDATE table_b SET seq = 0;
UPDATE user SET seq = 0;
Then you could run these statements one by one. These statements will zero out your seq columns.
Edit
You can also do
CONCAT('ALTER TABLE ',TABLE_NAME, ' DROP COLUMN seq;') AS stmt
to get a drop column statement for each table.
But, you might consider creating views of your tables that don't contain the seq columns, and then exporting to PostgreSQL using those views. If your tables are significant in size, this will save you a lot of time.

MySQL: IF table exists, truncate and insert ELSE create

Working only with MySQL (I have essentially no PHP knowledge), I need to have a table that's essentially a subset from a much larger table. The source table changes from time to time, losing some entries, gaining other new ones, and values changing for existing ones. I can describe what I want to happen, but can't seem to figure out a syntax of commands to make it work. I also know I can have two separate queries and just run whichever one I need, and I have that worked out, but I'd like to combine them if possible. Here's what I want:
IF the subset_table DOES NOT EXIST, create it as [select query], ELSE truncate the subset_table and insert [select query]
Like I said, I know there are other ways to do this - I could drop if exists/create, or I could just have two different sql files to run. I just want to know if I can do this as specified above.
Thoughts?
You can do this:
create table if not exists <tablename> . . .;
truncate table <tablename>;
insert into <tablename>(cols)
select blah blahblah . . .;
You don't need any if statements at all.
This can also be done through an SP (stored procedure)... makes it more readable and safe
DELIMITER $$
DROP PROCEDURE IF EXISTS `create_table_sp`$$
CREATE PROCEDURE `create_table_sp`()
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.TABLES WHERE table_name = '<table_name>'
AND table_schema = DATABASE() AND table_type = 'BASE TABLE') THEN
CREATE TABLE <subset_table_name>
AS SELECT * FROM <main_table_name>;
ELSE
TRUNCATE TABLE <subset_table_name>;
INSERT INTO <subset_table_name>
AS SELECT * FROM <main_table_name>;
END IF;
END$$
DELIMITER ;
CALL `create_table_sp`;
DROP PROCEDURE IF EXISTS `create_table_sp`;
There is also another way,
You could pass the table names as arguments to the SP, in this case sub_table_name and main_table_name
Make the above DML statements to a string using CONCAT()
Create a prepared statement out of it and execute
Hope this helped....