I have a stored procedure where I want to perform a INSERT operation. My INSERT query is stored in a php variable $query and I want to pass it as a parameter to my stored procedure.
$query_procedure = "CALL AddStation('$query','#LID')"
How can I get this query when I am creating the stored procedure?
Actually I want to use the same stored procedure for different INSERT queries
so that I dont have to pass individual parameters to the stored procedure.
Although you can technically achieve this, as shown below, I strongly discourage you from doing it. This a very bad idea. It simple doesn't make any sense and adds no value to your code. It's vulnarable to sql injections. You loose ability to use prepared statements for insert statements themselves. It's fragile and prone to errors since you're passing query strings, etc...
You better off without a stored procedure like this at all. Just use prepared statements in your client code.
DELIMITER$$
CREATE PROCEDURE AddARow(IN _sql TEXT, OUT _lid INT)
BEGIN
SET #sql = _sql;
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET _lid = LAST_INSERT_ID();
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Sample usage:
SET #lid = NULL;
SET #sql = 'INSERT INTO tablest (STATION_NAME, GEOGRAPHY) VALUES (''station1'',''India'')';
CALL AddARow(#sql, #lid);
SELECT #lid;
Here is SQLFiddle demo
Related
I've created a stored procedure to return a value for row count of any table I pass in as an "IN" parameter, and output that rowcount to an OUT parameter
PROCEDURE `GetCount`(in tblname varchar(255), out rowcount int)
BEGIN
SET #sql_text1 = concat('SELECT COUNT(*) FROM ',tblname);
SET #sql_text2 = concat(#sql_text1,' INTO ');
SET #sql_final = concat(#sql_text2, rowcount);
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END
when I open a query window in MySQL workbench and do the following:
set #tablename = 'my_table_name;
set #cnt = -9998;
call GetCount(#tablename,#cnt);
SELECT #cnt;
the value of #cnt is NULL.
Is my method of testing the stored proc incorrect, or is the stored proc to blame?
Your test methodology is valid, but you have made three errors in the procedure.
Error #1 you are using the wrong variable for the prepared statement.
PREPARE stmt1 FROM #sql_text1;
This should have been...
PREPARE stmt1 FROM #sql_final;
Error #2 This doesn't do what you intend:
SET #sql_final = concat(#sql_text2, rowcount);
This concatenates the value of #sql_text2 with the value of rowcount. Since rowcount is an out parameter, it is null at this point. If any argument to CONCAT() is null, then the result is also null, so you are actually setting #sql_final to null. If not for error #1, either the PREPARE or subsequent EXECUTE would have thrown an error about ...the right syntax to use near NULL at line 1.
Here's what you actually intended, the literal string 'rowcount':
SET #sql_final = concat(#sql_text2, 'rowcount');
...but that would also fail, because rowcount is a program variable. Prepared statements run with session scope, not program scope, so program variables are out of scope in a prepared statement.
The fix requires you to use a user-defined variable, which has session scope, and then copy it into the program variable, as #nbk illustrated in their answer.
SET #sql_final = concat(#sql_text2, '#rowcount');
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
SET rowcount = #rowcount;
Note that program variables like rowcount and user-defined variables like #rowcount are from completely different namespaces, so there's no need for the names to be the same and no need for the names to be different.
Error #3 is not strictly an error, in the sense that it isn't stopping your code from working, but here's a note about a potentially dangerous practice.
You are accepting a table name as input, which opens up a security vulnerability called SQL Injection, where malicious input can cause unexpected/unauthorized results. Even if the argument can be made that this input comes from a trusted source, that argument is disregarded as a matter of best practice, because future changes could invalidate that assumption. It is worth your time to learn to do this, and do it consistently so that it becomes second-nature to you.
You can safely escape a table name, column name, or other object identifier in MySQL by replacing any embedded backtick with a double backtick, then prepending and appending a single backtick on each end.
You can do this at the top of the procedure...
SET tblname = CONCAT('`',REPLACE(tblname,'`','``'),'`');
...or inline...
SET #sql_text1 = concat('SELECT COUNT(*) FROM ',CONCAT('`',REPLACE(tblname,'`','``'),'`'));
...but of course not both. In the second example, the nested CONCAT() isn't strictly necessary, so this would also work, but the intention is less obvious:
SET #sql_text1 = concat('SELECT COUNT(*) FROM ','`',REPLACE(tblname,'`','``'),'`');
Use this stored procdure:
DELIMITER //
DROP PROCEDURE IF EXISTS GetCount //
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetCount`(IN tblname varchar(255), OUT rowcount int)
BEGIN
SET #sql_text1 = concat('SELECT COUNT(*) FROM ',tblname);
SET #sql_text1 = concat(#sql_text1,' INTO ');
SET #sql_text1 = concat(#sql_text1, ' #rowcount;' );
PREPARE stmt1 FROM #sql_text1;
EXECUTE stmt1;
Set rowcount = #rowcount;
DEALLOCATE PREPARE stmt1;
END
//
DELIMITER ;
The idea is that mysql stores the count into the sessionvariable #rowcount which will be created automatically. The rest is simple getting the result to the proper variable.
I have a problem what I can solve in PHP but I want to solve in MySQL. Basicley I have a stored function, TASK_ASSIGN(id_task, operator).
I have an other function what SELECT exec FROM tasks. The tasks has a column exec, inside there I save TASK_ASSIGN(id_task, operator) format to execute.
I want to execute in a stored function or procedure if it is possible. Somebody can help me?
The solution was a stored procedure with this source:
BEGIN
DECLARE $execute_function VARCHAR(100);
-- Get the waiting function for execution
SELECT `exec` INTO $execute_function FROM `tasks` WHERE `id_task` = '1';
-- Create a session variable with the complete select
SET #query = CONCAT("SELECT ",$execute_function," AS result");
-- Execute the custom query
PREPARE execute_query FROM #query;
EXECUTE execute_query;
DEALLOCATE PREPARE execute_query;
END;
Thanks for wchiquito for suggesting the Prepared Statements.
I understand it's possible to have dynamic SQL in user defined stored procedure on MySQL (>=5.0.13). So if we have something like this:
CREATE PROCEDURE test()
BEGIN
SET #query = "SELECT * FROM temp";
PREPARE stmt FROM #query;
EXECUTE stmt;
END
My question is: how can I use the result of the dynamic statement that is executed?
If the result is a single value you can load it into a variable.
If your query retrieves a result set of multiple records you can load these into a cursor and loop through them record by record for further processing. See http://dev.mysql.com/doc/refman/5.0/en/cursors.html
I am getting syntax error on runnning this. Is it possible to use variables with limit without using concat function?
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ',_start,_end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
Error is
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 '_qry;
EXECUTE stmt;
You missed , before the offset.
CREATE PROCEDURE SP(_start INT,_end INT)
BEGIN
DECLARE _qry VARCHAR(500) DEFAULT CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM _qry;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
I think you have to change the DEFAULT DELIMITER first and adding PARAMETER DIRECTION before creating the STORED PROCEDURE.
There are good reasons to use prepared statements:
1. ) Save on query parsing
2.) Save on data conversion and copying
3.) Avoid SQL Injection
4.) Save memory on handling blobs
There are also drawbacks and chewats of using prepared statements:
1.) Query cache does not work
2.) Extra server round trip required if statement used only once
3.) Not all statements can be prepared. So you can’t use prepared API
exclusively you’ll need to fall back to normal API for some statements
4.) Newer and sometimes buggy code. I had a lot of problems with PHP
prepared statements. It is getting better but still it is less mature
than standard API
5.) You can’t use placeholders in place of all identifiers. For example you
can’t use them for table name. In certain version it even does not work for
LIMIT boundaries
6.) Inconvenient list handling. Unlike in for example PEAR emulated prepard
statements there is no nice way to pass list of values to IN
7.) Harder tracing. Logs were now fixed to include full statement text not
only “Execute” but in SHOW INNODB STATUS you would still see statements
without actual values – quite inonvenient for analyses.
try this one:
UPDATE 1
DELIMITER $$
CREATE PROCEDURE SP(IN _start INT,IN _end INT)
BEGIN
SET #iQuery = CONCAT('select * from tbl limit ', _start, ',', _end);
PREPARE stmt FROM #iQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
MySQL Syntax for Prepared Statements
delimiter //
drop procedure if exists SP //
create procedure SP(_start int,_end int)
begin
declare _qry varchar(500);
set #_qry = 'select * from tbl limit ?, ?';
set #start = _start;
set #end = _end;
prepare stmt from #qry;
execute stmt using #start, #end;
deallocate prepare stmt;
end; //
delimiter ;
call SP(1,2);
I am developing a simple WPF(C#) application where i am storing all insert, update and delete queries in a table. These queries are then executed on server one by one by simply selecting and then executing using ExecuteNonQuery() function in c#. The problem is that if have a large number of queries then it becomes very slow and sometimes due to network connection it is falling out.
Is it possible to create a stored procedure that can execute the queries stored within a table on the same server?
Please answer as soon as possible. Thanks.
Here is some code that i have tried till now.
DELIMITER $$
CREATE PROCEDURE `MyProc`(wo varchar(100))
BEGIN
DECLARE x INT;
DECLARE str text;
set x = 0;
select count(*) into x from tblqueries where isexecutedonserver = false and woid = wo;
SET str = '';
REPEAT
select `query` into str from tblqueries where id = 2976;
SET x = x - 1;
UNTIL x > 0
END REPEAT;
##select str;
prepare stmt from #str;
execute stmt;
deallocate prepare stmt;
END $$
DELIMITER ;
Please check and tell me where I am wrong.
This is simple (as simple as googling "mysql stored procedure execute")
Declare a CURSOR in your stored procedure.
Execute the cursor, then prepare a statement with the output:
PREPARE stmt FROM #sql;
EXECUTE stmt USING #myvar;
This code will help you with it:
MySQL Pass table name to cursor select
It sounds like what you need is a view.
Views (including updatable views) are available in MySQL Server 5.0. Views are stored queries that when invoked produce a result set. A view acts as a virtual table. Views are available in binary releases from 5.0.1 and up.
http://dev.mysql.com/doc/refman/5.0/en/views.html