Home > Blockchain >  Sending comma separated input params into the stored proc and looping each param in MYSQL
Sending comma separated input params into the stored proc and looping each param in MYSQL

Time:11-07

I have a simple stored procedure with comma separated input params. I will send Database Names in Json or Comma separated values. Like DB1,DB2,DB3 etc..; When ever I send that parameter will be loading that table in each of the Database. I'm looking for loop condition and splitting values.

EXEC   student_info (DBName = 'DB1,DB2,DB3,DB')

    DELIMITER &&  
    ALTER PROCEDURE student_info (IN DBName varchar(100))  
    BEGIN  
     **Splitting comma separated**
     **loop condition**  
        INSERT INTO @DBName.tbl_student(Name,Class)
        SELECT Name,Class FROM DB.student_info  ;  

    END &&  
    DELIMITER ;  

What is the best way?

CodePudding user response:

You need to use prepared statements (see: PREPARE)

drop procedure if exists student_info;
DELIMITER &&  
CREATE PROCEDURE student_info(IN dbname varchar(100))  
BEGIN  
    declare a CHAR(16);
    declare s VARCHAR(400);
    DECLARE cur1 CURSOR FOR
    with recursive cte as (
      select 
         @dbname as s1,
         substring_index(substring_index(@dbname,',',1),',',-1) as s2, 
         1 as x
      union all
      select 
         s1, 
         substring_index(substring_index(s1,',',x 1),',',-1), 
         x 1
      from cte 
      where x< (select length(s1)-length(replace(s1,',','')) 1)
      )
      select s2 from cte;

    open cur1;
     
    read_loop: loop
        fetch cur1 into a;
        set @s = CONCAT('INSERT INTO ',a,'.tbl_student(Name,Class) SELECT Name,Class FROM DB.student_info  ');
        PREPARE stmt1 FROM  @s;
        execute stmt1 ;
        deallocate prepare stmt1;
    END loop;

    close cur1;
END &&  
DELIMITER ;  

I tested with this:

drop table if exists DB1.tbl_student;
drop table if exists DB2.tbl_student;
drop table if exists DB3.tbl_student;
drop table if exists DB.tbl_student;
drop table if exists DB.student_info;
create table DB.tbl_student(name varchar(100),class varchar(100));
create table DB1.tbl_student(name varchar(100),class varchar(100));
create table DB2.tbl_student(name varchar(100),class varchar(100));
create table DB3.tbl_student(name varchar(100),class varchar(100));

create table DB.student_info(name varchar(100),class varchar(100));
insert into DB.student_info values ('Willem', 'Mathematics');
insert into DB.student_info values ('John', 'Mathematics');
insert into DB.student_info values ('Trudy', 'Mathematics');

CALL   student_info ('DB1,DB2,DB3,DB');

After this the data checked to be copied from student_info to the different tbl_student tables.

NOTE: I would not create those tables, and copy the data, but I would use a view:

create view db1.tbl_student as select name,class from db.student_info;

When you create a view, there is no need to copy the data to the other database, because this view will be updated automatically when records in the table db.student_info are updated/deleted or inserted.

P.S. Above was testen on MySQL 8.x. Some functionality that is not available in earlier versions of MySQL (like WITH) is used.

CodePudding user response:

(Answer to the original question, before the edit)

Use FIND_IN_SET instead of a loop

SELECT Name,Class 
FROM student_info 
where FIND_IN_SET(ID, studentID);

CodePudding user response:

create the function as follow query for separate your value:

CREATE FUNCTION [dbo].[SplitComaToTable](@input AS Varchar(4000) )
RETURNS
 @Result TABLE(Value BIGINT)
AS
BEGIN
      DECLARE @str VARCHAR(500)
      DECLARE @ind Int
      IF(@input is not null)
      BEGIN
            SET @ind = CharIndex(',',@input)
            WHILE @ind > 0
            BEGIN
                  SET @str = SUBSTRING(@input,1,@ind-1)
                  SET @input = SUBSTRING(@input,@ind 1,LEN(@input)-@ind)
                  INSERT INTO @Result values (@str)
                  SET @ind = CharIndex(',',@input)
            END
            SET @str = @input
            INSERT INTO @Result values (@str)
      END
      RETURN
END 

then use this query to select your value as table and set condition on query:

SELECT Value FROM dbo.SplitComaToTable(@yourIds)
 where Value =yourCondition
  • Related