Is there a easy way to rename a table in procedure? - mysql

I am using MariaDB 10.1 SQLyog 11.5
I've renamed the table using below query.
ALTER TABLE old_name RENAME new_name
But there are many stored procedures that reference 'old_name'. I've opened all the SP creation query and changed. Because I don't know which SP has a query that reference old_name table.
Is there a way to know which SP has queries that reference old_name table?

By this INFORMATION_SCHEMA.ROUTINES you can fetch the text available in the stored procedure
Please could try this query: (not verified)
SELECT ROUTINE_NAME
FROM INFORMATION_SCHEMA.ROUTINES
WHERE ROUTINE_DEFINITION LIKE '%old_name%'
-- AND ROUTINE_TYPE = "PROCEDURE" -- Filter only if need SPs
ORDER BY ROUTINE_NAME;
Reference from this page

You can it do like this:
Create RENAME Query
SELECT CONCAT ('RENAME TABLE ',
GROUP_CONCAT(t.TABLE_SCHEMA,'.',t.TABLE_NAME,' TO ', t.TABLE_SCHEMA,'.',REPLACE(t.TABLE_NAME,'old','NEW') SEPARATOR ' , ')
) INTO #sql
FROM information_schema.TABLES t
WHERE t.TABLE_TYPE = 'BASE TABLE'
AND t.TABLE_SCHEMA IN ('SCHEMA1','SCHEMA2')
AND t.TABLE_NAME LIKE 'old_table%';
ONLY to verify
SELECT #sql;
Prepare and execute it
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Related

MySql query for each wordpress multisite

I'm attempting a query that pulls information for each site in a Wordpress multisite environment. Here's what I have for reference:
SELECT
#optionTable:=CONCAT('p1m8z_', blog_id, '_options') AS optionTable,
(SELECT option_value FROM #optionTable WHERE option_name = 'blogname') AS blogName
FROM p1m8z_blogs
Though this code doesn't execute, it illustrates what I'm attempting to accomplish.
I know that I can't use a variable as a table name unless it's in a prepared statement so I tried slapping a prepared statement into the subquery:
SELECT
#optionTable = CONCAT('p1m8z_', blog_id, '_options') AS optionTable,
(
PREPARE stmt1 FROM "SELECT option_value FROM ? WHERE option_name = 'blogname'";
EXECUTE stmt1 USING #optionTable;
DEALLOCATE PREPARE stmt1;
) AS blogName
FROM p1m8z_blogs
That doesn't seem to execute either. Can I even put a prepared statement inside a subquery?
How can I write this statement so that it executes?
Both variables and parameters are treated as if they are string values. You cannot use a variable or a parameter as an identifier (i.e. a table name).
You must just concatenate any table names into the string before it is prepared.
SELECT CONCAT('p1m8z_', blog_id, '_options') INTO #optionTable
FROM p1m8z_blogs;
SET #query = CONCAT('SELECT option_value FROM `', #optionTable,
'` WHERE option_name = ''blogname''');
PREPARE stmt1 FROM #query;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
The syntax you showed where you embed the PREPARE/EXECUTE inside another query as if it's a subquery is not valid. Only SELECT can be used inside a subquery.

How to mimic pgsql row_to_array()

I wish to get a JSON_OBJECT of a table.
While pgsql has row_to_Json, MySQL does not, and I wish to mimic this.
Of course, I could do this..
SELECT JSON_ARRAYAGG(JSON_OBJECT(id, name)) FROM my_table;
However, if I do not know the names of the fields, and I wish to do something like this:
SELECT JSON_ARRAYAGG(JSON_OBJECT(*)) FROM my_table;
Of course, this does not work. So I tried:
SET #fields = (select group_concat(my_table.res) FROM (SELECT COLUMN_NAME AS res FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='my_table') AS my_table);
SELECT JSON_OBJECT(#fields) FROM my_table;
Which does not work also, because a single string is passed to JSON_OBJECT.
How to get the JSON representation of a row from any table?
You need to use a stored procedure to execute dynamic SQL. The procedure should contain code like this:
SET #fields = (
select group_concat('"', column_name, '", `', column_name, '`')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME=table_name_param
);
SET #sql = CONCAT('SELECT JSON_OBJECT(', #fields, ') FROM `', table_name_param, '`';
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Add column to MySQL (not MariaDB) table only if it does not exist using SQL only

I have read this question and the solutions but they are more or less not applicable to my case. I have only SQL option and the PROCEDURE should be avoided, we may not have the required permission.
This is a SQL script that creates missing tables, columns and indexes etc. (schema update)
I see that in MariaDB we can use IF NOT EXISTS clause but this is not available in MySQL. Is there any similar way or workaround available in MySQL?
Using the IF() in a SET statement to come up with the logic works for me:
SET #s = (SELECT IF(
(SELECT COUNT(1)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'your_table'
AND table_schema = 'your_schema'
AND column_name = 'column_name'
) > 0,
"SELECT 1",
"ALTER TABLE your_table ADD column_name VARCHAR(100)"
));
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

How to convert an SQL select query into a formatted HTML table within a MySQL function

I'm looking for a way to generate valid HTML code within MySQL (without PHP) by converting any query output into an HTML table.
Here's my progress so far and evidently, I'm stuck. I hope I can get some help, thanks.
1. "dynSQL" - A procedure to take any Select query and create a named table out of it
Since MySQL doesn't allow dynamic queries in functions, I'm calling a procedure that creates a named table, tmp. I can't use a temporary table because info about temporary tables is not available in information_schema (in mysql 5.6)
CREATE DEFINER=`root`#`%` PROCEDURE `dynSQL`(SQL_QUERY TEXT)
BEGIN
set #SQLQ := 'Drop table if exists tmp;';
PREPARE stmt from #SQLQ;
Execute stmt;
SET #SQLQ := concat('create table tmp as ',SQL_QUERY);
PREPARE stmt from #SQLQ;
Execute stmt;
-- I'm adding a auto increment ID column to be able to loop through the rows later
SET #SQLQ := "ALTER TABLE tmp add column CustColHTML_ID INT NOT NULL AUTO_INCREMENT FIRST, ADD primary KEY Id(CustColHTML_ID)";
PREPARE stmt from #SQLQ;
Execute stmt;
DEALLOCATE PREPARE stmt;
END
2. "MakeHTML" - Function to read from the table tmp and return a formatted HTML table
CREATE DEFINER=`root`#`%` FUNCTION `MakeHTML`() RETURNS text CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE HTML text default "<TABLE><TR>";
DECLARE rowCount int default 0;
DECLARE i int default 0;
select concat('<TR>',group_concat('<TD>',column_name,'</TD>' separator ''),'</TR>') into html from information_Schema.`columns` where table_name='tmp';
Select max(CustColHTML_ID) into rowCount from `tmp`; -- Set the row counter
WHILE i<=rowCount DO
-- What do I do here? How do I loop through the columns of table tmp?
set i:=i+1;
END WHILE;
RETURN HTML;
END
As you can see, I'm stuck at looping through the unknown and dynamic columns of table tmp. I read about how a cursor can be used here, but all the examples I saw make use of known columns and assign those into named variables. However, since the query itself is dynamic, I wouldn't know the names of the columns.
I'd really appreciate your time and assistance, thanks!
p.s. I've posted this as a new question because my earlier question was marked as closed as being too broad. I subsequently edited my question but it was still showing as Closed. I've therefore deleted the older question and replaced it with this one.
With a sample table as such:
CREATE TABLE tmp (ID INT, Col1 INT, Col2 INT);
The SQL you would need to generate your HTML is:
SELECT CONCAT('<table>', GROUP_CONCAT(CONCAT('<tr><td>',ID,'</td><td>',Col1,'</td><td>',Col2,'</td><tr>')), '</table>')
FROM tmp;
You can generate this using the INFORMATION_SCHEMA:
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp';
It is then just a case of executing this:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle
ADDENDEUM
Forgot to include table headers:
SET #SQL = (
SELECT CONCAT
(
'SELECT CONCAT(''<table><tr>'',',
GROUP_CONCAT(CONCAT('''<th>'',''', COLUMN_NAME, ''',''</th>''')),
', ''</tr>'', GROUP_CONCAT(CONCAT(''<tr>'', ',
GROUP_CONCAT(CONCAT('''<td>'',', COLUMN_NAME, ',''</td>''')),
', ''</tr>'')), ''</table>'') FROM tmp'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tmp'
);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Example on SQL Fiddle

SQL: deleting tables with prefix

How to delete my tables who all have the prefix myprefix_?
Note: need to execute it in phpMyAdmin
You cannot do it with just a single MySQL command, however you can use MySQL to construct the statement for you:
In the MySQL shell or through PHPMyAdmin, use the following query
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_name LIKE 'myprefix_%';
This will generate a DROP statement which you can than copy and execute to drop the tables.
EDIT: A disclaimer here - the statement generated above will drop all tables in all databases with that prefix. If you want to limit it to a specific database, modify the query to look like this and replace database_name with your own database_name:
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_schema = 'database_name' AND table_name LIKE 'myprefix_%';
Some of the earlier answers were very good.
I have pulled together their ideas with some
notions from other answers on the web.
I needed to delete all tables starting with 'temp_'
After a few iterations I came up with this block of code:
-- Set up variable to delete ALL tables starting with 'temp_'
SET GROUP_CONCAT_MAX_LEN=10000;
SET #tbls = (SELECT GROUP_CONCAT(TABLE_NAME)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'my_database'
AND TABLE_NAME LIKE 'temp_%');
SET #delStmt = CONCAT('DROP TABLE ', #tbls);
-- SELECT #delStmt;
PREPARE stmt FROM #delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I hope this is useful to other MySQL/PHP programmers.
show tables like 'prefix_%';
copy the results and paste them into a text editor or output the query to a file, use a few search and replaces to remove unwanted formatting and replace \n with a comma
put a ; on the end and add drop table to the front.
you'll get something that looks like this:
drop table myprefix_1, myprefix_2, myprefix_3;
#andre-miller solution is good but there is even better and slightly more professional that will help you execute all in one go. Still will need more than one command but this solution will allow you to use the SQL for automated builds.
SET #tbls = (SELECT GROUP_CONCAT(TABLE_NAME)
FROM information_schema.TABLES
WHERE TABLE_NAME LIKE 'myprefix_%');
PREPARE stmt FROM 'DROP TABLE #tbls';
EXECUTE stmt USING #tbls;
DEALLOCATE PREPARE stmt;
Note: this code is platform dependant, it's for MySQL but for sure it could be implemented for Postgre, Oracle and MS SQL with slight changes.
SELECT CONCAT("DROP TABLE ", table_name, ";")
FROM information_schema.tables
WHERE table_schema = "DATABASE_NAME"
AND table_name LIKE "PREFIX_TABLE_NAME%";
I drop table successfully by edit query to like this
SET GROUP_CONCAT_MAX_LEN=10000;
SET FOREIGN_KEY_CHECKS = 0;
SET #tbls = (SELECT GROUP_CONCAT(CONCAT('`', TABLE_NAME, '`'))
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'pandora'
AND TABLE_NAME LIKE 'temp_%');
SET #delStmt = CONCAT('DROP TABLE ', #tbls);
-- SELECT #delStmt;
PREPARE stmt FROM #delStmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET FOREIGN_KEY_CHECKS = 1;
Just another solution using GROUP_CONCAT so it will execute one drop query like
DROP TABLE table1,table2,..
SET #Drop_Stm = CONCAT('DROP TABLE ', (
SELECT GROUP_CONCAT(TABLE_NAME) AS All_Tables FROM information_schema.tables
WHERE TABLE_NAME LIKE 'prefix_%' AND TABLE_SCHEMA = 'database_name'
));
PREPARE Stm FROM #Drop_Stm;
EXECUTE Stm;
DEALLOCATE PREPARE Stm;
You can do that in one command with MySQL:
drop table myprefix_1, myprefix_2, myprefix_3;
You'll probably have to build the table list dynamically in code though.
An alternative approach would be to use the general purpose routine library for MySQL 5.
I just wanted to post the exact SQL I used - it's something of a mixture of the top 3 answers:
SET GROUP_CONCAT_MAX_LEN=10000;
SET #del = (
SELECT CONCAT('DROP TABLE ', GROUP_CONCAT(TABLE_NAME), ';')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'database_name'
AND TABLE_NAME LIKE 'prefix_%'
);
PREPARE stmt FROM #del;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I found that the prepared statements were a little tricky to get working for me but setting the GROUP_CONCAT_MAX_LEN was essential when you have a lot of tables. This resulted in a simple three-step process with cut-and paste from the mysql command line that worked great for me:
SET GROUP_CONCAT_MAX_LEN=10000;
SELECT CONCAT( 'DROP TABLE ', GROUP_CONCAT(table_name) , ';' )
AS statement FROM information_schema.tables
WHERE table_name LIKE 'myprefix_%';
Then carefully cut-and-paste the resulting long DROP statement.