Stored procedure doesn't create a new table - mysql

The procedure is suppose to take a existing table (oldtable) and create a new table (new_table_n). It's running, but not creating a new table. Any help will be appreciated.
DELIMITER $$
CREATE PROCEDURE P_DYN_TABLE(IN OLDTABLE VARCHAR(30), IN NEW_TABLE_N VARCHAR(30))
LANGUAGE SQL
BEGIN
DECLARE STATEMENT_1 VARCHAR(1000);
DECLARE CONTINUE HANDLER FOR SQLSTATE '42704'
SET STATEMENT_1 = '';
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
SET STATEMENT_1 = CONCAT('CREATE TABLE ',NEW_TABLE_N,' AS SELECT * FROM ',OLDTABLE,' WHERE 1=2');
PREPARE S1 FROM #STATEMENT_1;
EXECUTE S1;
SET STATEMENT_1 = CONCAT('INSERT INTO ',NEW_TABLE_N,' SELECT * FROM ',OLDTABLE);
PREPARE S2 FROM #STATEMENT_1;
EXECUTE S2;
END; $$

DELIMITER $$
CREATE PROCEDURE P_DYN_TABLE(IN OLDTABLE VARCHAR(30), IN NEW_TABLE_N VARCHAR(30))
BEGIN
DECLARE STATMENT VARCHAR(1000);
SET #STATMENT="";
SET #STATMENT = CONCAT('CREATE TABLE ',NEW_TABLE_N,' AS SELECT * FROM ',OLDTABLE,' WHERE 1=2');
PREPARE S1 FROM #STATMENT;
EXECUTE S1;
DEALLOCATE PREPARE S1;
SET #STATMENT = CONCAT('INSERT INTO ',NEW_TABLE_N,' SELECT * FROM ',OLDTABLE);
PREPARE S1 FROM #STATMENT;
EXECUTE S1;
DEALLOCATE PREPARE S1;
END; $$

Related

To compare two mysql database add missing tables and column using procedure

I have written a mysql procedure to compare two databases and add missing tables and columns but it show error i counld not spot the error i that procedure pls help me out to clear that error
DELIMITER $$
CREATE PROCEDURE database_comparison(IN original_db varchar(255),IN compare_db varchar(255))
BEGIN
DECLARE table_name_o varchar(255);
DECLARE column_name_o varchar(255);
DECLARE cursor_sts int default 0;
DROP TABLE IF EXISTS temp_db.original_database_list;
create temporary table temp_db.original_database_list SELECT TABLE_NAME,COLUMN_NAME,'table not exists' as flag_t,'column not exists' as flag_c FROM information_schema.`COLUMNS` where TABLE_SCHEMA=original_db and TABLE_NAME not like 'z%' and TABLE_NAME not like '%bk%';
DROP TABLE IF EXISTS temp_db.compare_database_list;
create temporary table temp_db.compare_database_list SELECT TABLE_NAME,COLUMN_NAME,'table not exists' as flag_t,'column not exists' as flag_c FROM information_schema.`COLUMNS` where TABLE_SCHEMA=compare_db and TABLE_NAME not like 'z%' and TABLE_NAME not like '%bk%';
update temp_db.original_database_list a join temp_db.compare_database_list b on a.TABLE_NAME=b.TABLE_NAME set a.flag_t='',b.flag_t='';
update temp_db.original_database_list a join temp_db.compare_database_list b on a.TABLE_NAME=b.TABLE_NAME and a.COLUMN_NAME=b.COLUMN_NAME set a.flag_c='',b.flag_c='';
DECLARE table_cursor CURSOR FOR select distinct TABLE_NAME from temp_db.original_database_list where flag_t<>'';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET cursor_sts=1;
OPEN table_cursor;
table_loop:LOOP
IF cursor_sts=1 THEN
SET cursor_sts=0;
LEAVE table_loop;
END IF;
FETCH table_cursor INTO table_name_o;
create table compare_db.table_name_o like original_db.table_name_o;
END LOOP table_loop;
CLOSE table_cursor;
SET table_name_o='';
DECLARE column_cursor CURSOR FOR select distinct TABLE_NAME,COLUMN_NAME from temp_db.original_database_list where flag_t='' and flag_c<>'';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET cursor_sts=1;
OPEN column_cursor;
column_loop:LOOP
IF cursor_sts=1 THEN
LEAVE table_loop;
END IF;
FETCH column_cursor INTO table_name_o,column_name_o;
SET #query =(SELECT concat('alter table `',compare_db,'`.`',table_name_o,'` add `',column_name_o,'` ',column_type,' not null;') FROM information_schema.`COLUMNS` where TABLE_NAME=table_name_o and a.COLUMN_NAME=column_name_o and TABLE_SCHEMA=original_db);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP column_loop;
CLOSE column_cursor;
END $$
DELIMITER ;
**this is the corrected procedure it works**
DELIMITER $$
DROP PROCEDURE IF EXISTS database_comparison$$
CREATE PROCEDURE database_comparison(IN original_db varchar(255),IN compare_db varchar(255))
BEGIN
DECLARE table_name_o varchar(255);
DECLARE column_name_o varchar(255);
DECLARE cursor_sts int default 0;
DEClARE table_cursor CURSOR FOR
select distinct TABLE_NAME from temp_db.original_database_list where flag_t<>'';
DECLARE column_cursor CURSOR FOR
select distinct TABLE_NAME,COLUMN_NAME from temp_db.original_database_list where flag_t='' and flag_c<>'';
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET cursor_sts=1;
DROP TABLE IF EXISTS temp_db.original_database_list;
create table temp_db.original_database_list SELECT TABLE_NAME,COLUMN_NAME,'table not exists' as flag_t,'column not exists' as flag_c FROM information_schema.`COLUMNS` where TABLE_SCHEMA=original_db and TABLE_NAME not like 'z%' and TABLE_NAME not like '%bk%';
DROP TABLE IF EXISTS temp_db.compare_database_list;
create table temp_db.compare_database_list SELECT TABLE_NAME,COLUMN_NAME,'table not exists' as flag_t,'column not exists' as flag_c FROM information_schema.`COLUMNS` where TABLE_SCHEMA=compare_db and TABLE_NAME not like 'z%' and TABLE_NAME not like '%bk%';
ALTER TABLE temp_db.original_database_list ADD index(TABLE_NAME,COLUMN_NAME);
ALTER TABLE temp_db.compare_database_list ADD index(TABLE_NAME,COLUMN_NAME);
update temp_db.original_database_list a join temp_db.compare_database_list b on a.TABLE_NAME=b.TABLE_NAME set a.flag_t='',b.flag_t='';
update temp_db.original_database_list a join temp_db.compare_database_list b on a.TABLE_NAME=b.TABLE_NAME and a.COLUMN_NAME=b.COLUMN_NAME set a.flag_c='',b.flag_c='';
OPEN table_cursor;
table_loop:LOOP
FETCH table_cursor INTO table_name_o;
IF cursor_sts=1 THEN
SET cursor_sts=0;
LEAVE table_loop;
END IF;
SET #query1 =concat('create table ',compare_db,'.',table_name_o,' like ',original_db,'.',table_name_o);
PREPARE stmt1 FROM #query1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP table_loop;
CLOSE table_cursor;
SET table_name_o='';
OPEN column_cursor;
column_loop:LOOP
FETCH column_cursor INTO table_name_o,column_name_o;
IF cursor_sts=1 THEN
LEAVE column_loop;
END IF;
SET #query =(SELECT concat('alter table `',compare_db,'`.`',table_name_o,'` add `',column_name_o,'` ',column_type,' not null;') FROM information_schema.`COLUMNS` where TABLE_NAME=table_name_o and COLUMN_NAME=column_name_o and TABLE_SCHEMA=original_db);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP column_loop;
CLOSE column_cursor;
END $$
DELIMITER ;

Stored procedure to loop through a list of tables deleting data in batches of 100000 in MySQL

I have 2 schemas with exactly the same tables schema_oltp and schema_olap. I want to delete from selected tables in schema_oltp only the data which already exists in schema_olap. The tables I want to delete from are listed in a table called archived_to_delete. For each of the tables listed in archived_to_delete, I need to delete the data in batches of 100 000. This is what I have so far. It only deletes 100 000 in each table and stops. I want it to continue until there is no data in schema_oltp which also exists in schema_olap:
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `schema_oltp`.`schemaDeletes`(IN from_schema VARCHAR(100), IN to_schema VARCHAR(100))
BEGIN
DECLARE v_tname varchar(100);
DECLARE v_pkey varchar(455);
DECLARE v_upfield varchar(455);
DECLARE done INT DEFAULT 0;
DECLARE v_limit INT DEFAULT 100000;
DECLARE v_deleted INT;
DECLARE table_cursor CURSOR FOR SELECT a.table_name, a.column_name
FROM INFORMATION_SCHEMA.COLUMNS a
INNER JOIN archived_to_delete b
ON a.table_name = b.table_name
WHERE TABLE_SCHEMA = 'schema_oltp'
AND COLUMN_KEY='PRI'
ORDER BY b.archived_to_delete_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN table_cursor;
REPEAT
FETCH table_cursor INTO v_tname, v_pkey;
IF NOT done THEN
SET v_deleted=0;
SET #sql = CONCAT('DELETE FROM ',from_schema,'.', v_tname, ' WHERE ',v_pkey,' IN (SELECT ', v_pkey, ' FROM ',to_schema,'.', v_tname, ') limit ',v_limit,';');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET v_deleted=v_deleted+1;
IF v_deleted = v_limit THEN
commit;
SET v_deleted=0;
END IF;
SELECT CONCAT('Deleting...',v_tname);
END IF;
UNTIL done END REPEAT;
CLOSE table_cursor;
END$$
DELIMITER ;

pass table name as parameter to cursor in mysql stored procedure

While implementing cursor I am unable to pass the table name as parameter to the select query declared in the cursor. How could I pass the table name as parameter to taht query ?
DELIMITER //
Drop PROCEDURE IF EXISTS GetRecord;
CREATE PROCEDURE GetRecord(IN hr int,IN TableName varchar(50))
BEGIN
declare done int DEFAULT 0;
declare ID int DEFAULT 0;
declare name varchar(25);
declare cur1 cursor for SELECT id ,name FROM TableName;
declare continue handler for not found set done=1;
SET #query = concat('update Student set no=no+? where id=?');
PREPARE stmt from #query;
open cur1;
igmLoop: loop
fetch cur1 into ID,name;
SELECT ID;
IF done = 1 THEN
LEAVE igmLoop;
END IF;
SET #id = ID;
SET #HR =hr;
EXECUTE stmt USING #HR,#id;
end loop igmLoop;
close cur1;
DEALLOCATE PREPARE stmt;
END;//
DELIMITER ;

Backup stored procedure only copies one table

I´ve been trying to create a stored procedure that will copy my database to another database. The problem is that only the first table is copying. Do you guys see any errors in the code?
DELIMITER $$
DROP PROCEDURE IF EXISTS fes_backup $$
CREATE PROCEDURE do_backup (IN name_bbdd VARCHAR(20), IN new_name_bbdd VARCHAR(20))
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE name_table VARCHAR(20);
DECLARE cur1 CURSOR FOR SELECT table_name FROM information_schema.tables
WHERE table_schema=name_bbdd AND table_type="base table";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
OPEN cur1;
bucle: LOOP
FETCH cur1 INTO name_table;
IF done=1 THEN
LEAVE bucle;
END IF;
SELECT CONCAT("Copio ",name_table," a nova base de dades ",new_name_bbdd);
SET #aux = CONCAT("CREATE TABLE ",name_table," LIKE ", name_bbdd, ".", name_table);
PREPARE stmt1 FROM #aux;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET #aux = CONCAT("INSERT INTO ",name_table," SELECT * FROM ", name_bbdd, ".", name_table);
PREPARE stmt1 FROM #aux;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP bucle;
CLOSE cur1;
END$$
DELIMITER ;
Thanks a lot!

Querying multiple databases at once

I have WordPress instances with each in its own database. For an update I need to query all active plugins, that are stored in a table 'wp_options' and accessible via
WHERE option_name='active_plugins'
How can I access all active plugin settings (spread over multiple databases) and output them in one single SQL result? I know the database.tablename syntax, but how do I go on from there with the above Where statement?
A request in a single database would look like this:
SELECT option_value
FROM `database`.`wp_options`
WHERE option_name="active_plugins"
SELECT option_value
FROM `database1`.`wp_options`
WHERE option_name="active_plugins"
UNION
SELECT option_value
FROM `database2`.`wp_options`
WHERE option_name="active_plugins"
The solution by Pentium10 is good but its drawback is that you have to extend the query for every schema to be included. The below solution uses a prepared statement to produce a result set for all schemas on your MySQL server which have the wp_options table. This should be more convenient for you.
DROP PROCEDURE IF EXISTS `MultipleSchemaQuery`;
DELIMITER $$
CREATE PROCEDURE `MultipleSchemaQuery`()
BEGIN
declare scName varchar(250);
declare q varchar(2000);
DROP TABLE IF EXISTS ResultSet;
create temporary table ResultSet (
option_value varchar(200)
);
DROP TABLE IF EXISTS MySchemaNames;
create temporary table MySchemaNames (
schemaName varchar(250)
);
insert into MySchemaNames
SELECT distinct
TABLE_SCHEMA as SchemaName
FROM
`information_schema`.`TABLES`
where
TABLE_NAME = 'wp_options';
label1:
LOOP
set scName = (select schemaName from MySchemaNames limit 1);
set #q = concat('select option_value from ', scName, '.wp_options where option_name=\'active_plugins\'');
PREPARE stmt1 FROM #q;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
delete from MySchemaNames where schemaName = scName;
IF ((select count(*) from MySchemaNames) > 0) THEN
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
SELECT * FROM ResultSet;
DROP TABLE IF EXISTS MySchemaNames;
DROP TABLE IF EXISTS ResultSet;
END
$$
DELIMITER ;
CALL MultipleSchemaQuery();
Gruber's answer works great, but it has a syntax error --- there's a spurious comma at the end of line 10. Here is the code, with syntax error fixed:
DELIMITER $$
CREATE PROCEDURE `MultipleSchemaQuery`()
BEGIN
declare scName varchar(250);
declare q varchar(2000);
DROP TABLE IF EXISTS ResultSet;
create temporary table ResultSet (
option_value varchar(200)
);
DROP TABLE IF EXISTS MySchemaNames;
create temporary table MySchemaNames (
schemaName varchar(250)
);
insert into MySchemaNames
SELECT distinct
TABLE_SCHEMA as SchemaName
FROM
`information_schema`.`TABLES`
where
TABLE_NAME = 'wp_options';
label1:
LOOP
set scName = (select schemaName from MySchemaNames limit 1);
set #q = concat('select option_value from ', scName, '.wp_options where option_name=\'active_plugins\'');
PREPARE stmt1 FROM #q;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
delete from MySchemaNames where schemaName = scName;
IF ((select count(*) from MySchemaNames) > 0) THEN
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
SELECT * FROM ResultSet;
DROP TABLE IF EXISTS MySchemaNames;
DROP TABLE IF EXISTS ResultSet;
END
$$
Yet another example of querying multiple databases using procedure, cursor, union all and prepared statement. Does not require drop and delete permissions:
USE `my_db`;
DROP PROCEDURE IF EXISTS `CountAll`;
DELIMITER $$
CREATE PROCEDURE `CountAll`(IN tableName VARCHAR(255))
BEGIN
DECLARE db_name VARCHAR(250);
DECLARE exit_loop BOOLEAN;
DECLARE union_query TEXT DEFAULT '';
DECLARE my_databases CURSOR FOR
SELECT DISTINCT `table_schema`
FROM `information_schema`.`tables`
WHERE
`table_schema` LIKE 'myprefix\_%' AND
`table_name` = tableName;
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET exit_loop = TRUE;
OPEN my_databases;
get_database: LOOP
FETCH my_databases INTO db_name;
IF exit_loop THEN
-- remove trailing UNION ALL statement
SET union_query = TRIM(TRAILING ' UNION ALL ' FROM union_query);
LEAVE get_database;
END IF;
SET union_query = concat(union_query, 'SELECT COUNT(*) AS qty FROM ',
db_name, '.', tableName, ' UNION ALL ');
END LOOP get_database;
CLOSE my_databases;
SET #final_query = concat('SELECT SUM(qty) FROM (', union_query,
') AS total;');
PREPARE stmt1 FROM #final_query;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END$$
DELIMITER ;
CALL CountAll('wp_options');