create multiple views with a mysql stored procedure - mysql

I wanted to build around 900 views(1 view for 1 table and based on 2 conditions) and i have all the table names in a table in mysql environment. I have created a stored proc . For test purpose i used limit 1.
I get below error when i call the sp.
Actually I re-wrote a mssql sp, did i miss anything here. please help
CALL ca_uim.sp_viewcreation_ontime() Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1 0.000 sec
USE `ca_uim`;
DROP procedure IF EXISTS `sp_viewcreation_ontime`;
DELIMITER $$
USE `ca_uim`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_viewcreation_ontime`()
BEGIN
DECLARE qos varchar(255);
DECLARE pos int;
DECLARE r_table varchar(255);
DECLARE view varchar(255);
DECLARE cview varchar(2048);
DECLARE done int default 0;
DECLARE qos_cursor CURSOR FOR SELECT DISTINCT qos,r_table FROM S_QOS_DATA ORDER BY 2 limit 1;
DECLARE continue handler for not found set done = 1;
OPEN qos_cursor;
-- Perform the first fetch.
FETCH qos_cursor INTO qos, r_table;
-- Check ##FETCH_STATUS to see if there are any more rows to fetch.
WHILE not done
DO
-- Check QOS name for '-' character & replace with '_' if exist
SET pos = LOCATE('-',qos, 1);
IF pos != 0
THEN
SET qos = INSERT(qos, pos, 1, '_');
END IF;
-- Check QOS name for '/' character & replace with '_' if exist
SET pos = LOCATE('/',qos, 1);
IF pos != 0
THEN
SET qos = INSERT(qos, pos, 1, '_');
END IF;
-- Check QOS name for '(' character & replace with '_' if exist
SET pos = LOCATE('(',qos, 1);
IF pos != 0
THEN
SET qos = INSERT(qos, pos, 1, '_');
END IF;
-- Check QOS name for ')' character & replace with '_' if exist
SET pos = LOCATE(')',qos, 1);
IF pos != 0
THEN
SET qos = INSERT(qos, pos, 1, '_');
END IF;
-- Create view
SET view = CONCAT('V_',qos);
SET cview = CONCAT('CREATE VIEW ',view,' AS ',
'SELECT Q.source,Q.target,Q.origin,Q.robot,Q.probe,D.sampletime,D.samplevalue,D.samplestdev,D.samplerate,D.tz_offset ',
'FROM S_QOS_DATA Q JOIN ',r_table,' D ON Q.table_id=D.table_id');
BEGIN
-- Suppress Error message for Views that don't exist
DECLARE CONTINUE HANDLER FOR 1051
set #stmt_str = CONCAT('DROP VIEW ',view);
prepare stmt from #stmt_str;
execute stmt;
deallocate prepare stmt;
END;
BEGIN
-- Create the View, Catch tables that don't have samplestdev & samplerate fields
DECLARE CONTINUE HANDLER FOR 1054
set #stmt_str = cview;
prepare stmt from #stmt_str;
execute stmt;
deallocate prepare stmt;
/* PRINT CONCAT('Created View: ' , view) */
END;
BEGIN
DECLARE CONTINUE HANDLER FOR 1054
SET cview = CONCAT('CREATE VIEW ',view,' AS ',
'SELECT Q.source,Q.target,Q.origin,Q.robot,Q.probe,D.sampletime,D.samplevalue,D.tz_offset ',
'FROM S_QOS_DATA Q JOIN ',r_table,' D ON Q.table_id=D.table_id');
set #stmt_str = cview;
prepare stmt from #stmt_str;
execute stmt;
deallocate prepare stmt;
/* PRINT CONCAT('Created View: ' , view) */
END;
-- PRINT 'qos: ' + #qos + ' ' + #r_table+' '+#view
-- PRINT #cview
-- This is executed as long as the previous fetch succeeds.
FETCH qos_cursor INTO qos, r_table;
END WHILE;
CLOSE qos_cursor;
END$$
DELIMITER ;
Thanks

Related

MySQL - Using dynamicsql on Update

I'm working with MySQL 5.6 and trying to a simple procedure seen below.
drop procedure if exists procsBook;
DELIMITER $$
CREATE PROCEDURE procsBook()
main:begin
DECLARE abc VARCHAR(256);
DECLARE def VARCHAR(256);
DECLARE field_name2 VARCHAR(256);
DECLARE field_names VARCHAR(256);
DECLARE bkid BIGINT(20);
SET abc:= NULL;
SET def:= NULL;
SET field_name2:= NULL;
SET field_names:= NULL;
SET bkid:= 0;
select a.field_name,b.column_name into abc,def from table1 a join table2 b where a.field_label=b.field_label and b.table_name='Table13' and b.section_name='English' group by a.field_name limit 1;
IF(abc is not null)
then
IF (SUBSTRING(abc,7,1)=1)
THEN
SELECT book1,bookId INTO field_names,bkid FROM shelf1 WHERE rowstate=0;
SET #vSelectQury = CONCAT('update shelf2 set def = ' , field_names, ' where book_id = ', bkid);
PREPARE vDynamicSSql FROM #vSelectQury;
EXECUTE vDynamicSSql;
DEALLOCATE PREPARE vDynamicSSql;
END IF;
END IF;
END $$
DELIMITER ;
Call:
call procsBook();
This is throwing the following error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where book_id = 22' at line 1
Any help please?
I think you need to add quotes around field_names.
SET #vSelectQury = CONCAT('update shelf2 set ', def, ' = \'' , field_names,
'\' where book_id = ', bkid); PREPARE vDynamicSSql FROM #vSelectQury;
(or if your setup is different you may need to change the escaping for ' character)
Updated you should not directly use def, but use the value of def in this case.

How to pass variable to UPDATE mysql query

I wanted to replace a value (1 > -1) in a table with the following commands
UPDATE table_name
SET column_name = replace(column_name, '1', '-1');
However,I decided to learn how to use stored programs in Mysql, since the number of columns are large with their regularly formatted namesn ('i01', 'i02',...).
Below is my trial:
DELIMITER $$
DROP PROCEDURE IF EXISTS example$$
CREATE PROCEDURE example()
BEGIN
DECLARE p INT;
DECLARE str VARCHAR(20);
SET p = 1;
WHILE p < 100 DO
IF p <= 9 THEN SET str = CONCAT('i0', p);
ELSE SET str = CONCAT('i', p);
END IF;
UPDATE target_table
SET `str` = replace(str, '1', '-1');
SET p = p + 1;
END WHILE;
END$$
When I source the script, which was OK and call the function, there says ERROR 1054 (42S22): Unknown column 'str' in 'field list.'
How can I pass the variable, in this case #str, inside UPDATE query?
I searched online and found PREPARE could be an answer but could not figure out how to use that in my case.
Yes, you were on the right track with PREPARE.. the only issue is you have to concate the query string with the variable name outside of the string to access its contents.
SET #A = (SELECT CONCAT("UPDATE target_table SET `", #str, "` = replace(str, '1', '-1');"));
PREPARE qry FROM #A;
EXECUTE qry;
DEALLOCATE PREPARE qry;
if the replace you have is related to your variable #str (because you dont have the # sign there I'm not sure if its an actual column or the variable) then you need to change #A a little bit
SET #A = (SELECT CONCAT("UPDATE target_table SET `", #str, "` = replace(", #str, ", '1', '-1');"));
DEMO
with your DECLAREs this should be your final query
DELIMITER $$
DROP PROCEDURE IF EXISTS example$$
CREATE PROCEDURE example()
BEGIN
DECLARE p INT;
DECLARE str VARCHAR(20);
DECLARE update_qry VARCHAR(200);
SET p = 1;
WHILE p < 100 DO
-- set up column name
IF p <= 9
THEN SET str = CONCAT('i0', p);
ELSE SET str = CONCAT('i', p);
END IF;
-- set up query to execute
SET update_qry = CONCAT("UPDATE target_table SET `", str, "` = replace(", str, ", '1', '-1');")
-- prepare execute and deallocate query
PREPARE qry FROM update_qry;
EXECUTE qry;
DEALLOCATE PREPARE qry;
-- increment counter for next column name
SET p = p + 1;
END WHILE;
END$$

Error when calling a SP from another one

I have created the following MySQL SP successfully..
CREATE DEFINER=`root`#`%` PROCEDURE `Common_Proc_Create_NewId`
(
TableName VARCHAR(250),
ColumnName VARCHAR(150),
OUT ReturnId BIGINT
)
BEGIN
DECLARE varb BIGINT;
SET #NewId:= CONCAT('SELECT (IFNULL(MAX(', ColumnName, '), 0) + 1) INTO ', varb, ' FROM ', TableName);
PREPARE Stmnt FROM #NewId;
EXECUTE Stmnt;
DEALLOCATE PREPARE Stmnt;
SET ReturnId = varb;
END$$
But when this was called from another SP I got the following error:
Error Code: 1064 You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'NULL' at line 1
Calling SP
CREATE DEFINER=`root`#`%` PROCEDURE `Masters_Proc_Create_BranchType`(
BranchTypName VARCHAR(100)
)
BEGIN
CALL Common_Proc_Create_NewId('Masters_BranchType', 'BranchTypeId', #Id);
INSERT INTO Masters_BranchType (BranchTypeId, BranchTypeName) VALUES (#Id, BranchTypName);
SELECT #Id;
END$$
In your stored procedure Common_Proc_Create_NewId the part into varb was causing the issue and think it's not allowed that way in a prepared statement (not sure though). Instead the way you are doing, try like below and it works fine (a sample code included)
delimiter //
CREATE PROCEDURE dynamic1(IN tbl VARCHAR(64), IN col VARCHAR(64), OUT ret int)
BEGIN
SET #s = CONCAT('SELECT #i := (IFNULL(MAX(', col, '), 0) + 1) FROM ', tbl);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set ret = #i;
END
//
delimiter ;
call dynamic1('test1','col',#id);
select #id;

MySQL Error 1064 : Stored procedure

thanks, It's work
It was on this 2 line :
SET valueName = CONCAT(valueName, ' ,', _valueSplit);
SET valueValue = CONCAT(valueValue,' ,', json(_entryData, _valueSplit));
I have declared the variable, but at NULL so CONCAT return NULL and the query go on NULL to
thanks to Devart for helping me
the post :
when I try to use my Stored Procedure I have this error
call _extract() Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
but I see nothing in the procedure
this my procedure, but no instruction NULL on it
CREATE PROCEDURE _extract()
BEGIN
DECLARE _entryType VARCHAR(45);
DECLARE _entryData VARCHAR(1024);
DECLARE _entryTime BIGINT(20);
DECLARE no_more_rows BOOLEAN;
DECLARE num_rows INT DEFAULT 0;
DECLARE entryCursor CURSOR FOR SELECT entryValue, entryTime FROM TrackingEntry;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET no_more_rows = TRUE;
OPEN entryCursor;
select FOUND_ROWS() into num_rows;
mainLoop: LOOP
FETCH entryCursor INTO _entryData, _entryTime;
IF no_more_rows THEN
CLOSE entryCursor;
LEAVE mainLoop;
END IF;
SET _entryType = json(_entryData, "type");
CALL split_string(json(_entryData, "data"), ",");
CALL _extractJson(_entryType, _entryData);
END LOOP mainLoop;
END$$
_extractJson procedure :
the next part of the extration of the data
CREATE PROCEDURE _extractJson(`_entryType` VARCHAR(255))
BEGIN
DECLARE _valueSplit VARCHAR(255);
DECLARE valueName VARCHAR(255);
DECLARE valueValue VARCHAR(255);
DECLARE split_no_more_rows BOOLEAN;
DECLARE split_num_rows INT DEFAULT 0;
DECLARE splitCursor CURSOR FOR SELECT SQL_CALC_FOUND_ROWS _value FROM SplitValues;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET split_no_more_rows = TRUE;
OPEN splitCursor;
select FOUND_ROWS() into split_num_rows;
dataLoop: LOOP
FETCH splitCursor INTO _valueSplit;
IF split_no_more_rows THEN
CLOSE splitCursor;
LEAVE dataLoop;
END IF;
SET valueName = CONCAT(valueName, ' ,', _valueSplit);
SET valueValue = CONCAT(valueValue,' ,', json(_entryData, _valueSplit));
END LOOP dataLoop;
SET #query = CONCAT('INSERT INTO ',_entryType, ' (',valueName,') VALUES (',valueValue,')' );
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
--end stuffs here
END$$
to explain what i want to do
some Data are stored in trackingEntry, each row contain information about what the user do (in a social game) and where he come from (action, referer, and some other value)
theses data are stored in a Json format like that :
{
"type" : "tableName",
"data" : "row1,row2,row3",
"row1" : "value",
"row2" : "value",
"row3" : "value"
}
the type of the data (the action (connection, publish on wall)) it's a table's name of one of our dashboard application
The "data" is the list of the available datas
and after we have the Datas
The problem can be with a prepared INSERT statement, it seems that one of the variables is NULL. Try to comment prepared statements and select #query, you will see the problem -
SET #query = CONCAT('INSERT INTO ',_entryType, ' (',valueName,') VALUES (',valueValue,')' );
SELECT #query;
-- PREPARE stmt FROM #query;
-- EXECUTE stmt;
-- DEALLOCATE PREPARE stmt;
You have to add SQL_CALC_FOUND_ROWS in the select statement, so that the FOUND_ROWS() function works.
So change this line
DECLARE entryCursor CURSOR FOR SELECT entryValue, entryTime FROM TrackingEntry;
like this
DECLARE entryCursor CURSOR FOR SELECT SQL_CALC_FOUND_ROWS entryValue, entryTime FROM TrackingEntry;
You can read more about it here.

Stored procedure error on CALL

I am trying to call a procedure which compiles successfully but on calling I get this error:
Query: call proc5
Error Code: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL' at line 1
This is my Stored procedure:
DELIMITER $$
CREATE DEFINER = `root` #`localhost` PROCEDURE `proc5` ()
BEGIN
DECLARE done BOOL DEFAULT FALSE ;
DECLARE tablename VARCHAR (100) ;
DECLARE tracktables CURSOR FOR
SELECT
TABLE_NAME
FROM
information_schema.TABLES
WHERE TABLE_SCHEMA = 'db1' ;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = TRUE ;
OPEN tracktables ;
myloop :
LOOP
FETCH tracktables INTO tablename ;
IF done
THEN CLOSE tracktables ;
LEAVE myloop ;
END IF ;
SET #s = CONCAT(
'INSERT INTO db2.test1 SELECT * FROM ',
#tablename
) ;
PREPARE stmt1 FROM #s ;
EXECUTE stmt1 ;
DEALLOCATE PREPARE stmt1 ;
END LOOP ;
END $$
DELIMITER ;
Actually, I want to select all the tables from a database and insert those tables into one table which is in another database using MySQL Cursors. And when I call this stored procedure I get the above error.
The problem is that you are mixing declared variables and impromtu #vars.
var -> tablename does not equal var -> #tablename.
Change the set line to:
SET #s = CONCAT(
'INSERT INTO db2.test1 SELECT * FROM `'
,tablename
,'`'
) ;
Now it should work.
The backticks ` should not be needed, but are there just in case.