MySQL Error 1064 : Stored procedure - mysql

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.

Related

GROUP CONCAT is failing when Alphanumeric value is coming MYSQL stored procedure

I have sample procedure where I'm passing DB names as input param and it was looping fine and updating the statements.
Please find the Below one :
DELIMITER &&
CREATE PROCEDURE update_stmt (IN DBName varchar(100))
BEGIN
DECLARE _next TEXT DEFAULT NULL;
DECLARE _nextlen INT DEFAULT NULL;
DECLARE _value TEXT DEFAULT NULL;
DECLARE schemaname varchar(64);
iterator:
LOOP
IF CHAR_LENGTH(TRIM(_list)) = 0 OR _list IS NULL THEN
LEAVE iterator;
END IF;
SET _next = SUBSTRING_INDEX(_list,',',1);
SET _nextlen = CHAR_LENGTH(_next);
SET _value = TRIM(_next);
SET schemaname = _value;
SELECT concat('update ',schemaname, '.SAMPLE SET COL = 0 where ID IN (',GROUP_CONCAT(TICKET),');') AS statement
FROM Test.SAMPLE
INTO #sql;
PREPARE stmt from #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET _list = INSERT(_list,1,_nextlen + 1,'');
END LOOP;
END
When the Procedure executes it will create statement like the below if I print:
Update Test.sample SET COL = 0 WHERE ID IN (1,2,3)
For Example If I have ID Column like this in the table :
**ID**
1A
2B
3C
When I execute the procedure I expect to get the statement like below :
Update Test.sample SET COL = 0 WHERE ID IN ('1A','2B','3C')
But I'm getting error as
Unnkown column 1A in where clause
In the Groupconcat how I need to handle alphanumeric values and one more thing FROM Test.SAMPLE.
I'm passing variable in the place of DB Name it is giving error as schemaname.SAMPLE doesn't exist.
Please suggest
Provided ID column is a char string, add single quotes around the TICKET value .. GROUP_CONCAT(CONCAT('''', TICKET, '''')) ..
Also check if #sql is null (Test.SAMPLE is empty)
..
if #sql is not null then
PREPARE stmt from #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
end if;
To stop the proc gracefully at error provide an exit handler for SQLEXCEPTION. For example
CREATE PROCEDURE update_stmt (IN DBName varchar(100))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
/* Your error processing here */
END;
..
db-fiddle

create multiple views with a mysql stored procedure

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

Using prepared statements with cursor

I put the cursor declaration in the prepared statement and then executed it, then returns an error #1324 - Undefined CURSOR: getid.
How do I solve this problem?
delimiter ;;
drop procedure if exists test2;;
create procedure test2(table_id VARCHAR(25))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE id_new INT;
DECLARE stmt1 VARCHAR(1024);
DECLARE stmt2 VARCHAR(1024);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
SET #sqltext1 := CONCAT('DECLARE getid CURSOR FOR SELECT entryId FROM ',table_id,' ORDER BY entryId');
PREPARE stmt1 FROM #sqltext1;
EXECUTE stmt1;
SET #id_new = 1;
OPEN getid;
FETCH getid into id;
REPEAT
SET #sqltext2 := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
PREPARE stmt2 FROM #sqltext2;
EXECUTE stmt2 USING #new_id, id;
SET #id_new = #id_new + 1;
FETCH getid into id;
UNTIL done END REPEAT;
CLOSE getid;
END
;;
CALL test2('Test');
Some rules:
All declarations must be at one place in a sequence.
You can't use variable names in cursor declarations.
Handler declarations must be after cursor declarations.
You can't use local variable names (id) as bound parameters for
prepared statements. You can only use session variables (say #_id).
To overcome such problems, you can adopt following solution.
Define a temporary table using the input parameter to the SP.
Now declare the cursor on the same table and use it.
Drop the temporary table created.
Following example should work on your tables.
delimiter $$
drop procedure if exists test2$$
create procedure test2( table_id varchar(25) )
begin
set #temp_query = 'drop temporary table if exists temp_cursor_table';
prepare pst from #temp_query;
execute pst;
drop prepare pst; -- or
-- deallocate prepare pst;
set #temp_table_query='create temporary table temp_cursor_table ';
set #temp_table_query=concat( #temp_table_query, ' select entryId from ' );
set #temp_table_query=concat( #temp_table_query, table_id );
set #temp_table_query=concat( #temp_table_query, ' order by entryId' );
prepare pst from #temp_table_query;
execute pst;
drop prepare pst;
-- now write your actual cursor and update statements
-- in a separate block
begin
declare done int default false;
declare id int;
declare id_new int;
declare stmt1 varchar(1024);
declare stmt2 varchar(1024);
declare getid cursor for
select entryId from temp_cursor_table order by entryId;
declare continue handler for not found set done = 1;
set #id_new = 1;
open getid;
fetch getid into id;
repeat
set #sqltext2 := concat( 'update ', table_id );
set #sqltext2 := concat( #sqltext2, ' set entryId = ? where entryId = ?' );
set #_id = id;
prepare stmt2 from #sqltext2;
execute stmt2 using #new_id, #_id;
set #id_new = #id_new + 1;
fetch getid into id;
until done end repeat;
close getid;
end;
end;
$$
delimiter ;
Now call the procedure with table_id value.
call test2( 'Test' );

Use variable when declaring cursor

I want to pass the parameter to the procedure and use it for the table name on declaring cursor. The following code returns an error message: #1146 - Table 'db.table_id' doesn't exist.
How do I use the parameter when declaring cursor?
Thanks
delimiter ;;
drop procedure if exists reset_id;;
create procedure reset_id(table_id VARCHAR(25))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE id_new INT;
DECLARE getid CURSOR FOR SELECT entryId FROM table_id ORDER BY entryId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
SET #id_new = 1;
OPEN getid;
FETCH getid into id;
REPEAT
UPDATE table_id SET entryId = #id_new WHERE entryId = id;
SET #id_new = #id_new + 1;
FETCH getid into id;
UNTIL done END REPEAT;
CLOSE getid;
END
;;
CALL reset_id('Test');
After modifying the procedure, still returns an error #1324 - Undefined CURSOR: getid. How do i solve this problem?
delimiter ;;
drop procedure if exists test2;;
create procedure test2(table_id VARCHAR(25))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE id_new INT;
DECLARE stmt1 VARCHAR(1024);
DECLARE stmt2 VARCHAR(1024);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
SET #sqltext1 := CONCAT('DECLARE getid CURSOR FOR SELECT entryId FROM ',table_id,' ORDER BY entryId');
PREPARE stmt1 FROM #sqltext1;
EXECUTE stmt1;
SET #id_new = 1;
OPEN getid;
FETCH getid into id;
REPEAT
SET #sqltext2 := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
PREPARE stmt2 FROM #sqltext2;
EXECUTE stmt2 USING #new_id, id;
SET #id_new = #id_new + 1;
FETCH getid into id;
UNTIL done END REPEAT;
CLOSE getid;
END
;;
CALL test2('Test');
The table name has to be specified in the SQL text; it cannot be a variable.
To accomplish what you are trying to do, you are going to need to dynamically create a string that contains the SQL text you want to execute.
To prepare the statement from arbitrary string:
SET #sqltext := CONCAT('UPDATE ',table_id,' SET entryId = ? WHERE entryId = ?');
PREPARE stmt FROM #sqltext;
Note that the table_id value is getting incorporated into a string variable, and then the PREPARE statement is (essentially) turning that string into an actual SQL statement.
To execute the prepared statement and supply values for the bind variables, you'd do something like this:
EXECUTE stmt USING #new_id, #id;
You can re-execute a prepared statement multiple times, without needing to prepare it again. So, the PREPARE would be done before your loop, the EXECUTE can be done inside the loop.
Once you are finished with the statement, following the loop, the best practice is to deallocate the statement like this:
DEALLOCATE PREPARE stmt;
NOTE:
The restriction about the table name not being a variable actually applies to all identifiers in a SQL statement, including names of tables, views, columns, functions, etc. Those all have to be literals in the SQL text, just like the reserved keywords do.

error in my procedure MySQL find value INT in all tables database

I want find a number of UserId from all tables call searchUser(3,'UserId')
error: 0 14:30:14 call searchUser(3,'UserId') 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
DELIMITER $$
CREATE PROCEDURE `searchUser`( in_search int(11),in_column_name varchar(50) )
READS SQL DATA
BEGIN
DECLARE trunc_cmd VARCHAR(50);
DECLARE searchUserId int (11);
DECLARE db,tbl,clmn CHAR(50);
DECLARE done INT DEFAULT 0;
DECLARE COUNTER INT;
DECLARE table_cur CURSOR FOR
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM `',table_name,'` WHERE `', in_column_name,'` = "',in_search,'"') ,table_name,column_name FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'comments' and column_name=in_column_name ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
PREPARE trunc_cmd FROM "TRUNCATE TABLE temp_details;";
EXECUTE trunc_cmd ;
OPEN table_cur;
table_loop:LOOP
FETCH table_cur INTO db, tbl, clmn;
SET #searchUserId = searchUserId;
SELECT searchUserId;
PREPARE searchUserId FROM #searchUserId;
EXECUTE searchUserId;
SET COUNTER = #CNT_VALUE;
SELECT COUNTER;
IF COUNTER>0 THEN
INSERT INTO temp_details VALUES(db,tbl,clmn);
END IF;
IF done=1 THEN
LEAVE table_loop;
END IF;
END LOOP;
CLOSE table_cur;
SELECT * FROM temp_details;
END
Problem must be due to:
DECLARE searchUserId int (11);
and:
SET #searchUserId = searchUserId;
SELECT searchUserId;
PREPARE searchUserId FROM #searchUserId;
EXECUTE searchUserId;
I assume that you are thinking searchUserId has a value. But nowhere in the code you assigned a value to it. By default it is a NULL. And hence the statement EXECUTE searchUserId is translate to EXECUTE NULL. This caused the error you specified.
To resolve it, you should first assign a proper value to the searchUserId variable declared.
BTW, why are you using the same variable name searchUserId for a local variable, global variable, and statement alias? It would confuse the readers of the program and hence is not advised to practice.
I guess problem lies in this statement-creation-statement:
SELECT concat('SELECT COUNT(*) INTO #CNT_VALUE FROM `',table_name,'` WHERE `', in_column_name,'` = "',in_search,'"') ,table_name,column_name FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = 'comments' and column_name=in_column_name ;
Please execute the statement standalone and see what you get.