Stored procedure with recursive call using mysql - mysql

enter image description hereget legside from binary
I have tried using stored procedure with recursive call. i need to display relevant name based on emp_name based on leg1
but it showing error like #1414 - OUT or INOUT argument 2 for routine sample.getVolume is not a variable or NEW pseudo-variable in BEFORE trigger
Here is my code,
DELIMITER $$
CREATE PROCEDURE getVolume( IN param_name VARCHAR(255), OUT result VARCHAR(255 ))
BEGIN
SELECT val INTO result FROM employee WHERE emp_name = param_name ;
IF result IS NULL THEN
select result;
ELSE
CALL getVolume(result, '');
END IF;
END $$
DELIMITER ;
SET ##GLOBAL.max_sp_recursion_depth = 255;
SET ##session.max_sp_recursion_depth = 255;
call getVolume('new', #result);
select #result;

The answer of #Shadow is correct. Here a practical example that can help you:
DELIMITER //
DROP TABLE IF EXISTS `employee`//
DROP PROCEDURE IF EXISTS `getVolume`//
CREATE TABLE `employee` (
`emp_name` VARCHAR(255),
`val` VARCHAR(255)
)//
INSERT INTO `employee` (`emp_name`, `val`)
VALUES
('demo', 'new'),
('new', 'd.new'),
('d.new', 'view'),
('view', 'hello'),
('hello', NULL)
//
CREATE PROCEDURE `getVolume`(
IN `param_name` VARCHAR(255),
OUT `result` VARCHAR(255)
)
BEGIN
DECLARE `next_param_name` VARCHAR(255);
SELECT `val` INTO `next_param_name`
FROM `employee`
WHERE `emp_name` = `param_name`;
IF `next_param_name` IS NULL THEN
SET `result` := `param_name`;
ELSE
-- CALL `getVolume`(`result`, '');
CALL `getVolume`(`next_param_name`, `result`);
-- SET `result` := CONCAT(`param_name`, ',', IFNULL(`result`, ''));
END IF;
END//
DELIMITER ;
SQL Fiddle demo

The problem is that when you call getResult() within getresult, you pass an empty string constant as a parameter:
CALL getVolume(result, '');
Declare a variable instead and pass that as a parameter. After the getVolume call do not forget to concatenate what is returned by getVolume to the result variable with a separator character. Are you sure that 255 characters will be enough to hold all values?

Related

How to create an empty view (or array) and later insert data in it?

This is because I am creating a procedure which generates items (by calling another function) which then finally needs to return me an array sort of collection including all the values.
I am thinking I can do it with a temporary table or View.
DROP PROCEDURE IF EXISTS getAllStrings $$
CREATE PROCEDURE getAllStrings(IN idString varchar(256), OUT finalSeparate VARCHAR(256))
BEGIN
SELECT LENGTH(idString) - LENGTH(REPLACE(idString, ',', '')) INTO #noOfCommas;
IF #noOfCommas = 0
THEN
SELECT idString;
ELSE
CREATE OR REPLACE VIEW v AS SELECT NULL AS SPLIT_VALUES WHERE FALSE;
SET #y = 1;
WHILE #y <= #noOfCommas DO
SELECT splitString(idString, ', ', #y) INTO #tempSeparate;
SET #y = #y + 1;
INSERT INTO v (SPLIT_VALUES) values(#tempSeparate);
END WHILE;
SELECT SPLIT_VALUES FROM v;
END IF;
END $$
It says that
Target table v is not insertable-into
How do I do it? I even tried changing the algorithm to merge but it didn't work.
The one with a table works, but I am looking for a data structure that can hold it better, maybe #json, I don't know.
DELIMITER $$
DROP FUNCTION IF EXISTS splitString $$
CREATE FUNCTION splitString (
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255) deterministic
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '') $$
DROP PROCEDURE IF EXISTS getAllStrings $$
CREATE PROCEDURE getAllStrings(IN idString varchar(256), OUT finalSeparate VARCHAR(256))
BEGIN
SELECT LENGTH(idString) - LENGTH(REPLACE(idString, ', ', '')) INTO #noOfCommas;
IF #noOfCommas = 0
THEN
SELECT idString;
ELSE
DROP TABLE IF EXISTS TEMP_SEP_STRINGS;
CREATE TABLE IF NOT EXISTS TEMP_SEP_STRINGS( SPLIT_VALUES VARCHAR(256));
SET #y = 1;
WHILE #y <= #noOfCommas DO
SELECT splitString(idString, ', ', #y) INTO #tempSeparate;
SET #y = #y + 1;
INSERT INTO TEMP_SEP_STRINGS(SPLIT_VALUES) values(#tempSeparate);
END WHILE;
SELECT * FROM TEMP_SEP_STRINGS;
END IF;
END $$
CALL getAllStrings('b, a', #multiple);
A temporary table has been the best option for me yet. It gets deallocated when the session ends or the connection is closed (although you can drop it before that happens) and just gobbles up whatever data you give it.
No need to define its columns and stuff and you can probably use it anywhere via SELECT command such as with the SQL IN operator.
An example:
CREATE TEMPORARY TABLE temp_table
SELECT tree_id FROM TREES WHERE fruit_type='Apple';

How to only with SQL select column form table A, split its by separator and insert separated values to other table?

sorry for my english :)
I need (only with SQL) select all column values form table A, split its by separator and insert separated values to other table?
For example, i have table like this:
ID, NAME, MAGIC
1, Marty, ACD ACFX U128BH
and i need export "MAGIC" value to separate table like this:
ID, USERID, MAGIC
1, 1, ACD
2, 1, ACFX
3, 1, U128BH
How to do it? I found eg. SQL insert data to other table after split string, but this is MS SQL syntax (?) and im using MySQL.
Thanx for reply
EDIT THIS ANSWER TO MUCH YOUR WORK
#drop table magic_t;
create table magic_t(
id int,
name varchar(100),
magic varchar(100)
);
#drop table split_insert;
create table split_insert(
split_value varchar(100)
);
insert into magic_t values(1,'nam1','VAL1 VAL2 VAL3');
insert into magic_t values(1,'nam1','VAL4 VAL5 VAL3');
#drop function strSplit;
DELIMITER ;;
CREATE FUNCTION strSplit(x varchar(255), delim varchar(12), pos int) returns varchar(255)
return replace(substring(substring_index(x, delim, pos), length(substring_index(x, delim, pos - 1)) + 1), delim, '');;
DELIMITER ;
#drop procedure split_table;
DELIMITER ;;
CREATE procedure split_table ()
begin
DECLARE done INT DEFAULT 0;
DECLARE while_condition boolean default true;
DECLARE counter INT DEFAULT 0;
DECLARE magic_value varchar(100);
declare splited_value varchar(100);
DECLARE colum_list CURSOR FOR SELECT magic FROM magic_t;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; -- to stop loop when fetch is over
OPEN colum_list;
REPEAT FETCH colum_list INTO magic_value;
if done =0 then
set counter =1;
set while_condition = true;
while(while_condition) do
set splited_value = strSplit(magic_value,' ',counter) ;
if splited_value <>'' then
insert into split_insert values(splited_value);
end if;
if splited_value='' then set while_condition=false; end if;
set counter =counter+1;
end while;
end if;
UNTIL done -- here stop repeat when done =1
END REPEAT;
end ;;
DELIMITER ;
call split_table ();
select * from split_insert;

Incorrect number of arguments for PROCEDURE

Define procedure:
DELIMITER $$
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
proc_label:BEGIN
IF tablename IS NULL THEN
SELECT 'Null detect';
LEAVE proc_label;
END IF;
SELECT 'after';
END;
$$
DELIMITER ;
Call Procedure:
CALL SP_Reporting();
Error :
ERROR 1318 (42000): Incorrect number of arguments for PROCEDURE
cds.SP_Reporting ; expected 1, got 0
How pass var by default like SP_Reporting(IN tablename = 'default value' VARCHAR(20))
When you are making your stored procedure, you can assign a value to your input, so there is no need to pass parameters while you are calling the proc.
We usually assign NULL and for making parameters optional, we use this method.
tablename VARCHAR(20) = NULL
Your complete script:
DELIMITER $$
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20) = NULL)
proc_label:BEGIN
IF tablename IS NULL THEN
SELECT 'Null detect';
LEAVE proc_label;
END IF;
SELECT 'after';
END;
$$
DELIMITER ;
EDIT
MySQL is not accepting optional parameters. So one way is to pass NULL value in your stored procedure and check it with IF statement inside your proc.
DELIMITER $$
CREATE PROCEDURE SP_Reporting(IN tablename VARCHAR(20))
proc_label:BEGIN
IF tablename IS NULL THEN
-- Do something;
ELSE
-- Do something else;
END IF;
END;
$$
DELIMITER ;
You have to pass the table name in the procedure call statement like:
CALL SP_Reporting(table_name);
you can't pass default in call statement.
You can assign default value before calling the procedure.
or use OUT instead of IN as a parameter.
you miss the parameter :tablename
you should like this :
call SP_Reporting('any varchar')
or
call SP_Reporting(null)

MySql stored functions: Not works

I have the following function:
DROP FUNCTION IF EXISTS saveTableRow;
DELIMITER $$
CREATE FUNCTION saveTableRow(adapter_id int(10), view_id int(10),name varchar(255)) RETURNS TINYINT(1)
BEGIN
DECLARE retOK TINYINT DEFAULT 0;
IF (SELECT COUNT(*) FROM `tables` WHERE `adapter_id`=adapter_id AND `view_id`=view_id AND `name`=name ) = 0 THEN
INSERT INTO `tables` (`adapter_id`,`view_id`,`name`) VALUES (adapter_id, view_id, name);
SET retOK = 1;
END IF;
RETURN retOK;
END;
$$
DELIMITER ;
When i call the function to insert a new row with
SELECT saveTableRow(3,1,'Text');
I get the result '0' and there is no new row saved.
It might be a name collision problem. The name of the column is the same with the name of you parameter. You need to change the name of your parameter that is different from the name of your column. eg,
DROP FUNCTION IF EXISTS saveTableRow;
DELIMITER $$
CREATE FUNCTION saveTableRow(
_adapter_id int(10),
_view_id int(10),
_name varchar(255))
RETURNS TINYINT(1)
BEGIN
DECLARE retOK TINYINT DEFAULT 0;
IF (SELECT COUNT(*)
FROM `tables`
WHERE `adapter_id`=_adapter_id AND
`view_id`=_view_id AND
`name`=_name ) = 0 THEN
INSERT INTO `tables` (`adapter_id`,`view_id`,`name`)
VALUES (_adapter_id, _view_id, _name);
SET retOK = 1;
END IF;
RETURN retOK;
END;
$$
DELIMITER ;
change the if as follows as try please:
IF ((SELECT COUNT(*) FROM `tables` WHERE `adapter_id`=adapter_id AND `view_id`=view_id AND `name`=name ) < 1)

Error in stored procedure - column count does not match value

I've created a stored procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `zero`.`sp_for_insert_into_account_db`$$
CREATE PROCEDURE `zero`.`sp_for_insert_into_account_db` (usr_key char(6),usr_name varchar(15),usr_password varchar(15),OUT output_message INT)
BEGIN
DECLARE no_of_row INT;
SELECT COUNT(*) INTO no_of_row from account_db;
IF no_of_row < 4 THEN
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (',usr_key,usr_name,usr_password,')');
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET output_message=1;
ELSE
SET output_message=0;
END IF;
END$$
DELIMITER ;
I'm calling it with query
call sp_for_insert_into_account_db('a','b','c',#output_ message);
The error is like:
Column count does not match value...
I'm passing 4 arguments...
Why is this error occurring?
I've already checked with this syntax (by default parameter is IN type)
sp_for_insert_into_account_db(IN usr_key char(6),
IN usr_name varchar(15),
IN usr_password varchar(15),
OUT output_message INT)
Problem is also here:
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (',usr_key,usr_name,usr_password,')');
You are trying to insert 3 values and the concatenation returns 1
use this instead:
SET #s = CONCAT('insert into account_db (USR_KEY,USR_NAME,USR_PWD) VALUES (\'',usr_key,'\',\'',usr_name,'\',\'',usr_password,'\')');
Not entirely sure why you're using prepared statements/dynamic sql when you dont need to ?? See the following example which i've cleaned up for you a little:
drop procedure if exists sp_for_insert_into_account_db;
delimiter #
create procedure sp_for_insert_into_account_db
(
in p_usr_key char(6),
in p_usr_name varchar(15),
in p_usr_pwd varchar(15),
out p_output_message tinyint unsigned
)
begin
declare v_no_of_row int unsigned default 0;
set p_output_message=0;
select count(*) into v_no_of_row from account_db;
if v_no_of_row < 4 then
insert into account_db(usr_key, usr_name, usr_pwd) values (p_usr_key, p_usr_name, p_usr_pwd);
set p_output_message = 1;
end if;
end#
delimiter ;
call sp_for_insert_into_account_db (...);
EDIT
are you a COBOL PROGRAMMER FROM THE 1970'S AND IS THAT WHY YOU HAVE TO USE CAPS ?