How can I use values returned from Cursor as table names in mysql procedures ?
DECLARE cur CURSOR FOR
select table_name, column_name
from information_schema.columns
where table_schema = 'foo' and table_name like 'bar%';
OPEN cur;
loop1: LOOP
FETCH cur
INTO table_val, column_val;
IF no_more_rows THEN
CLOSE cur;
LEAVE loop1;
END IF;
update table_val SET column_val ...
This throws error that foo.table_val doesnt exist. How can I get the actual table name to be passed to the select statement ?
Change update table_val SET column_val ... into
SET #sql = CONCAT('UPDATE ', table_val, ' SET ', column_val, ' = whatever WHERE...');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Read more about it here.
But note that you can not parameterize table and column names. This only works with values.
I will also share my fix. hope it will help someone too.
-- set to "$$" as we have ";" inside of Procedure. MySQL will be confused.(is this part of Procedure or should I run it now?)
DELIMITER $$
CREATE PROCEDURE UpdateTable()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE _table_name CHAR(255);
DECLARE cur CURSOR FOR
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'db_name' AND table_type = "BASE TABLE";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
My_loop: LOOP
FETCH cur INTO _table_name;
SET #my_table_name = _table_name;
IF done THEN
LEAVE My_loop;
END IF;
SET FOREIGN_KEY_CHECKS = 0;
SET #stmt = CONCAT('ALTER TABLE ', #my_table_name, ' CONVERT TO CHARACTER SET utf8;');
PREPARE stmt1 FROM #stmt;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET FOREIGN_KEY_CHECKS = 1;
END LOOP;
CLOSE cur;
END$$
-- set to normal. ";"
DELIMITER ;
Related
I want to make an event that every 5 seconds create a backup of my tables in a tables_old.
I would also like to know how I can check if a table has not been modified and not make that copy.
This is my code:
create event ejer5
on schedule every 5 second
do
begin
DECLARE done INT DEFAULT FALSE;
DECLARE table_name varchar(30);
DECLARE cursor1 CURSOR FOR select table_name
from information_schema.tables
where table_type = 'BASE TABLE'
and table_schema not in ('information_schema', 'sys',
'performance_schema','mysql')
and table_schema = "world"
order by update_time desc;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
open cursor1;
bucle:loop
fetch cursor1 into table_name;
IF done THEN
LEAVE bucle;
END IF;
SET #c = CONCAT('CREATE TABLE `',table_name,'_old', '` LIKE `',table_name,'`');
PREPARE stmt from #c;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end loop;
close cursor1;
end //
following code is running fine, what I need to ask how can I use a variable instead of a table name written in cursor select statement?
block5: begin
declare var1 int default 0;
DECLARE done TINYINT DEFAULT FALSE;
DECLARE cursor1 CURSOR FOR SELECT co_srno FROM vu_company where katscode in ('OGDC', 'LUCK', 'MCB');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cursor1;
my_loop: LOOP
FETCH cursor1 INTO var1;
IF done THEN
LEAVE my_loop;
ELSE
set #s = concat("insert into ", #temp_table_name_scrnr_data, " (sr_no) values (", var1, ")");
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END LOOP;
end block5;
I have a server with multiple schemas. I need to find specyfic email address. Every schema looks pretty much te same, they have same structure. What i wanted to do is to write a script to for displaying dbname and specyfic data related to given email . Heres my script, but it do not work:(
DELIMITER $$
#Drop procedure if exists SearchAllDb $$
Create procedure SearchAllDb()
BEGIN
DECLARE DB_NAME Varchar(50);
DECLARE done INT default FALSE;
DECLARE CURSOR_ALL_DB_NAMES CURSOR FOR
SELECT schema_name from information_schema.schemata
WHERE schema_name like 'itools_%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN CURSOR_ALL_DB_NAMES;
myloop: LOOP
FETCH CURSOR_ALL_DB_NAMES INTO DB_NAME;
IF done THEN LEAVE myloop;
END IF;
WHILE done != TRUE DO
SET #SQL = CONCAT('select DB_NAME, id, sn, name, email
from',DB_NAME,'.`open_cases` where email like 'xxx#yahoo.com'');
prepare stmt from #SQL;
execute stmt;
deallocate prepare stmt;
END WHILE;
CLOSE CURSOR_ALL_DB_NAMES;
END;
DELIMITER ;
I have something similar written in t-sql and it works...
DECLARE #DB_NAME VARCHAR(50);
DECLARE CURSOR_ALL_DB_NAMES CURSOR FOR
SELECT name FROM master.sys.databases
WHERE name like 'pickup-%' and name!= 'pickup-stored';
OPEN CURSOR_ALL_DB_NAMES;
FETCH NEXT FROM CURSOR_ALL_DB_NAMES INTO #DB_NAME
WHILE ##Fetch_Status = 0
BEGIN
Print #DB_NAME;
exec ('select '''+ #DB_NAME + ''' as db, id, sn, email from ['+
#DB_NAME+'].dbo.requests where email in (''xxx#live.com'')');
FETCH NEXT FROM CURSOR_ALL_DB_NAMES INTO #DB_NAME
END
CLOSE CURSOR_ALL_DB_NAMES;
DEALLOCATE CURSOR_ALL_DB_NAMES;
Looks like you were doing fine up until you introduced the WHILE.
THE WHILE is redundant since you are using a LOOP, you should remove those lines.
The LOOP doesn't have an END.
The CONCAT statement will treat the first use of DB_NAME as one of your column names and there are some quoting issues with the LIKE.
The ';' at the end of the procedure should be '$$' which you have specified as your DELIMITER.
I've taken a few liberties with your variable names but this tidied up version should illustrate the points.
DELIMITER $$
DROP PROCEDURE IF EXISTS SearchAllDb $$
CREATE PROCEDURE SearchAllDb()
BEGIN
DECLARE db_name VARCHAR(64);
DECLARE done INT DEFAULT FALSE;
DECLARE cur CURSOR FOR
SELECT schema_name
FROM information_schema.schemata
WHERE schema_name LIKE 'itools_%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
myloop: LOOP
FETCH cur INTO db_name;
IF done THEN
LEAVE myloop;
END IF;
SET #SQL = CONCAT('SELECT ''', db_name, ''', id, sn, name, email
FROM `', db_name,'`.`open_cases`
WHERE email LIKE ''xxx#yahoo.com''');
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur;
END $$
DELIMITER ;
There's a very good CURSOR example in the documentation at https://dev.mysql.com/doc/refman/5.7/en/cursors.html which will help you with the structure of the procedure.
I have to following procedure trying to dynamically create a view.
CREATE DEFINER=`root`#`%` PROCEDURE `uspCreateViewFromTable`(IN ViewName varchar(255), IN TableName varchar(255))
BEGIN
#View Droppen falls sie schon erstellt wurde
SET #s = CONCAT('DROP VIEW IF EXISTS ',ViewName);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
# Verwendete Spalten filtern und Statement bauen
#SET #columns = CAST('SELECT ' AS VARCHAR(10));
DECLARE column varchar(500);
DECLARE column_cursor FOR SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = Tablename;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN column_cursor
read_loop: LOOP
FETCH column_cursor INTO column
# do something
SELECT column;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE column_cursor;
END
I get the Error "Missing END" and I have no idea why.
The syntax checker underlines the semikolon at the end of Line
DEALLOCATE PREPARE stmt;
When I move the dealloc to the end the syntac checker highlightes the semikolon at the line before.
EXECUTE stmt;
If I remove everthing after the dealloc it works.
Some problems:
DECLARE is permitted only inside a BEGIN ... END compound statement and must be at its start, before any other statements. See 13.6.3 DECLARE Syntax.
ERROR 1193 (HY000): Unknown system variable 'done'.
Check the syntax of cursors. See 13.6.6.2 Cursor DECLARE Syntax.
column is keyword and reserved word. See 9.3 Keywords and Reserved Words.
Missing some ;.
DELIMITER //
CREATE PROCEDURE `uspCreateViewFromTable`(
IN ViewName varchar(255),
IN TableName varchar(255)
)
BEGIN
/*
#View Droppen falls sie schon erstellt wurde
SET #s = CONCAT('DROP VIEW IF EXISTS ',ViewName);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
*/
# Verwendete Spalten filtern und Statement bauen
#SET #columns = CAST('SELECT ' AS VARCHAR(10));
-- DECLARE column varchar(500);
DECLARE `column` varchar(500);
DECLARE done BOOL DEFAULT FALSE;
/*
DECLARE column_cursor FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = Tablename;
*/
DECLARE column_cursor CURSOR FOR
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = Tablename;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
#View Droppen falls sie schon erstellt wurde
SET #s = CONCAT('DROP VIEW IF EXISTS ',ViewName);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- OPEN column_cursor
OPEN column_cursor;
read_loop: LOOP
-- FETCH column_cursor INTO column
FETCH column_cursor INTO `column`;
# do something
-- SELECT column;
SELECT `column`;
IF done THEN
LEAVE read_loop;
END IF;
END LOOP;
CLOSE column_cursor;
END//
DELIMITER ;
I can't drop a table from a procedure.
This is the procedure in which it gives me the error.
CREATE PROCEDURE `procDropAllTables`()
BEGIN
DECLARE table_name VARCHAR(255);
DECLARE end_of_tables INT DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT t.table_name
FROM information_schema.tables t
WHERE t.table_schema = DATABASE() AND t.table_type='BASE TABLE';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET end_of_tables = 1;
SET FOREIGN_KEY_CHECKS = 0;
OPEN cur;
tables_loop: LOOP
FETCH cur INTO table_name;
IF end_of_tables = 2 THEN
LEAVE tables_loop;
END IF;
SET #s = CONCAT('DROP TABLE IF EXISTS ' , table_name);
PREPARE stmt FROM #s;
EXECUTE stmt;
END LOOP;
CLOSE cur;
SET FOREIGN_KEY_CHECKS = 1;
END
I can drop drop tables if I do it manualy, so it isnt a user privileges problem