Pass a procedure name dynamically - mysql

Is it possible to pass a name of a procedure dynamically within another procedure?
The procedure name is stored in a table and based on criteria the name will be different.
If it is possible how would I accomplish this?
So far I have something like this:
SET $proc = CONCAT('CALL ',$queryString);
PREPARE stmt FROM CONCAT('CALL ', $queryString);
EXECUTE stmt;

Pretty close, just use correct prepared statement syntax:
create procedure sp_exec_proc(
in_proc char(64)
)
begin
set #proc = concat('CALL ',in_proc);
prepare stmt from #proc;
execute stmt;
end
You can then pass in the procedure name and optional parameters
call sp_exec_proc('sp_my_proc("ABC")')

Related

MySQL query, create table with variable

How do you include a variable into a create table query(.sql file)? I have tried everything to my knowledge, but it simply sets the #variable name itself as the table name instead of the actual variable.
(I.e it sets #preset as the name instead of "cart_")
SET #Preset='cart_';
CREATE TABLE IF NOT EXISTS `#preset,Customer` (....
You need dynamic sql. To do this, you are going to have to use prepared statements
Try something like:
SET #SQL = CONCAT('CREATE TABLE ',CONCAT('cart_',customer), ..;
PREPARE stmt FROM #SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Changing Multiple DB Fields to Lower Case

With phpMyAdmin, I can use the following SQL to change all values in the table.field mytable.Site to lower case...
UPDATE my_table SET Site=LOWER(Site)
I have a zillion tables that have this same field, and I'd like to change all of them to lower case. Is there a SQL command that will do that - change EVERY field named Site in every table to lower case (preferably without having to list every table that has that field)?
Not EXACTLY what you want,but pretty close.Tested on my machine.
First create a procedure
delimiter //
CREATE PROCEDURE test(IN tbl CHAR(64))
BEGIN
SET #s = CONCAT('UPDATE ',tbl,' SET Site=LOWER(Site)' );
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
//
delimiter ;
And for finding tables with a certain column name:
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME IN ('Site')
AND TABLE_SCHEMA='YourDB';
For calling the procedure
CALL test('tableName')

IN Clause dont work in MySQL for me

I am passing my parameter as 'Suburbun','Indigo' to retrieve records matching both Campaigns in below Stored Procedure created in MySql.
CREATE PROCEDURE `DemoSP`(Campaign VARCHAR(3000))
BEGIN
SET #query = CONCAT('Select * from vicidial_log WHERE campaign_id IN (?)');
PREPARE stmt FROM #query;
SET #CampaignID = Campaign;
EXECUTE stmt USING #CampaignID;
DEALLOCATE PREPARE stmt;
END;
It Doesn't give any rows!
But when i pass only 'Suburbun' in SP, it gives 6 Rows!
Where am i going wrong?
--Answer !
I tried as Lee Fentress commented in http://www.poolofthought.com/index.php/2008/12/28/a-comma-seperated-list-as-parameter-to-mysql-stored-procedure/ and peterm answer reflected similar coding,
It worked!
Thanks, but i find this negative mark as compared to SQL Server.
Gee, Thank you Guys!!
You won't be able to use USING in this case. You can just build the full query sting and execute it without parameters
DELIMITER $$
CREATE PROCEDURE DemoSP(Campaign VARCHAR(3000))
BEGIN
SET #query = CONCAT('SELECT * FROM vicidial_log WHERE campaign_id IN (', Campaign, ')');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Note: make sure that delimited values that you pass in Campaign are properly quoted (like you said they are) and quotes in values, if there is any, are escaped.
Here is SQLFiddle demo
Try this:
There is no need to use PREPARE STATEMENT. You can get the result using FIND_IN_SET() function
SELECT * FROM vicidial_log WHERE FIND_IN_SET(campaign_id, Campaign)
try this
"Select * from vicidial_log WHERE campaign_id IN ('?')"
instead of
'Select * from vicidial_log WHERE campaign_id IN (?)'

Iterate MySQL schemas

Problem description
I have a single-tenant MySQL database setup. That is, I have one identical schema for each client.
Now I need to run a specific query for each client. That would be easy in a multi-tenant setting (where all clients share a single schema). With my setup however, I need to iterate the schemas. More generally, I want to access a schema whose name is given by a variable. How can that be done?
What I've tried
If I try USE varSchemaName (where varSchemaName is a varchar
variable), I get the error message ERROR 1314: USE is not allowed
in stored procedures.
If I try SELECT * FROM varSchemaName.MyTable I get
Error Code: 1146. Table 'varSchemaName.MyTable' doesn't exist. Apparently MySQL considers varSchemaName to be a literal, not a
variable.
Building on the answer from fancyPants, you can call that procedure within a loop from another procedure which queries information_schema.tables to identify the databases containing MyTable and then call fancyPants' procedure with the db names as a parameter. This method is easy if the databases have a consistent naming scheme or contain identically named objects, which sounds like the case here. The structure would be something like:
DELIMITER //
DROP PROCEDURE IF EXISTS mydriver //
CREATE PROCEDURE mydriver()
BEGIN
DECLARE varSchemaName VARCHAR(64);
DECLARE done BOOLEAN;
DECLARE cur CURSOR FOR
SELECT table_schema
FROM information_schema.tables
WHERE table_name = 'MyTable';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO varSchemaName;
IF done THEN
LEAVE read_loop;
CLOSE cur;
END IF;
CALL fancypants_proc(varSchemaName);
END LOOP;
END //
DROP PROCEDURE IF EXISTS fancypants_proc //
CREATE PROCEDURE fancypants_proc(IN varSchemaName VARCHAR(64))
BEGIN
SET #sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
CALL mydriver();
You have to build the statement first.
SET #sql = CONCAT('SELECT * FROM ', varSchemaName, '.MyTable');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You can read more about prepared statements here.
You might be tempted to use variables for tablenames, but that doesn't work. Those parameters are for values in where clauses and so on. The above way is the way to go.

use a variable for table name in mysql sproc

I'm trying to pass a table name into my mysql stored procedure to use this sproc to select off of different tables but it's not working...
this is what I"m trying:
CREATE PROCEDURE `usp_SelectFromTables`(
IN TableName varchar(100)
)
BEGIN
SELECT * FROM #TableName;
END
I've also tried it w/o the # sign and that just tells me that TableName doesn't exist...which I know :)
SET #cname:='jello';
SET #vname:='dwb';
SET #sql_text = concat('select concept_id,concept_name,',#vname,' from enc2.concept a JOIN enc2.ratings b USING(concept_id) where concept_name like (''%',#cname,'%'') and 3 is not null order by 3 asc');
PREPARE stmt FROM #sql_text;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
An extra bit that caused me problems.
I wanted to set the table name and field dynamically in a query as #kyle asked, but I also wanted to store the result of that query into a variable #a within the query.
Instead of putting the variable #a into the concat literally, you need to include it as part of the string text.
delimiter //
CREATE PROCEDURE removeProcessed(table_name VARCHAR(255), keyField VARCHAR(255), maxId INT, num_rows INT)
BEGIN
SET #table_name = table_name;
SET #keyField = keyField;
SET #maxId = maxId;
SET #num_rows = num_rows;
SET #sql_text1 = concat('SELECT MIN(',#keyField,') INTO #a FROM ',#table_name);
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
loop_label: LOOP
SET #sql_text2 = concat('SELECT ',#keyField,' INTO #z FROM ',#table_name,' WHERE ',#keyField,' >= ',#a,' ORDER BY ',#keyField,' LIMIT ',#num_rows,',1');
PREPARE stmt2 FROM #sql_text2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
...Additional looping code...
END LOOP;
END
//
delimiter ;
So in #sql_text1 assign the result of the query to #a within the string using:
') INTO #a FROM '
Then in #sql_text2 use #a as an actual variable:
,' WHERE ',#keyField,' >= ',#a,' ORDER BY '
It depends on the DBMS, but the notation usually requires Dynamic SQL, and runs into the problem that the return values from the function depend on the inputs when it is executed. This gives the system conniptions. As a general rule (and therefore probably subject to exceptions), DBMS do not allow you to use placeholders (parameters) for structural elements of a query such as table names or column names; they only allow you to specify values such as column values.
Some DBMS do have stored procedure support that will allow you to build up an SQL string and then work with that, using 'prepare' or 'execute immediate' or similar operations. Note, however, that you are suddenly vulnerable to SQL injection attacks - someone who can execute your procedure is then able to control, in part, what SQL gets executed.