I am attempting to execute the following prepared statement:
PREPARE stmt FROM 'SELECT * FROM Inventory I WHERE I.ParentId = ?';
EXECUTE stmt USING #parentId;
DEALLOCATE PREPARE stmt;
When I execute this statement, it returns the column headers with no rows. It should return 6 rows.
If I execute this same statement as a normal SQL statement without the PREPARE and EXECUTE statement, I get results, e.g.
SELECT * FROM Inventory I WHERE I.ParentId = parentId;
Results are returned. What am I doing wrong? Is there some kind of casting going on that is making my statement invalidate?
Update, parentId is passed in as a parameter, e.g.
CREATE DEFINER=`george`#`%` PROCEDURE `ListInventoryByParentId`(IN parentId INT)
User variable #parentId and procedure argument parentID are independent.
You need to set your user variable to procedure argument before executing statement.
SET #parentID = parentId;
Related
I am using a concatenate function to run a subquery in a stored procedure. This query is supposed to return a number but its returning NULL. Your help is appreciated.
set #Sl =Concat('select sum(etl_insert_rows) into #Times
from Table1
where etl_job_id in
(SELECT etl_job_id
FROM Table2 where etl_target_table="',#TabName,'")');
Prepare stmt from #Sl;
Execute stmt;
I am trying to create a stored procedure in mysql which creates a new table on every request copies the content from another table and extracts the required data and finally drops the table. The stored procedure is quite large so I cant have EXECUTE after every query and thus I am trying to execute the query all together in a semicolon separated format. But on final execution I get Error Code: 1064.
Is the approach I am trying possible, or is there a better approach.
SET tableName = (SELECT CONCAT("table",(UNIX_TIMESTAMP(NOW()))));
SET #tquery =CONCAT('CREATE TABLE `',tableName,'` (select pt.* from post_table pt join on user u on pt.user_id=u.id where pt.client="client",pt.group="group");');
SET #tquery = CONCAT(#tquery,' SELECT * FROM ',tableName,';');
SET #tquery = CONCAT(#tquery,' DROP TABLE ',tableName,';');
PREPARE stmt FROM #tquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
No, it is not possible. PREPARE / EXECUTE stmt can execute only one query at a time, many statements cannot be combined. See documentation: http://dev.mysql.com/doc/refman/5.0/en/prepare.html
... a user variable that contains the text of the SQL statement. The text must represent a single statement, not multiple statements.
Anyway, to simplify your code I would create a simple procedure:
CREATE PROCEDURE exec_qry( p_sql varchar(100))
BEGIN
SET #tquery = p_sql;
PREPARE stmt FROM #tquery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
/
and I would call this procedure in the main procedure, in this way:
CALL exec_qry( 'CREATE TABLE t2 AS SELECT * FROM test');
CALL exec_qry( 'SELECT * FROM t2');
CALL exec_qry( 'SELECT count(*) FROM t2');
CALL exec_qry( 'SELECT avg(x) FROM t2');
CALL exec_qry( 'DROP TABLE t2');
Take a look at a demo: http://www.sqlfiddle.com/#!2/6649a/6
How do I cache dynamic query from store procedure?
Right now I have created my store procedure like this :
CREATE PROCEDURE usp_MyProcedure (
IN UserID INT,
....
)
BEGIN
SET #sqlQuery = CONCAT("SELECT Name From Users WHERE UserID > ", UserID, " AND UserID IN ( SELECT UserID FROM OtherTable WHERE UserID = ", UserID, " ) Order by Name")
PREPARE stmt FROM #sqlQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
But this kind of query does not cached. so, every time it gets more time to execute/process query.
Now I have tried some other method like this:
CREATE PROCEDURE usp_MyProcedure (
IN UserID INT,
....
)
BEGIN
SET #UserID = UserID;
SET #sqlQuery = "SELECT Name From Users WHERE UserID > ? AND UserID IN ( SELECT UserID FROM OtherTable WHERE UserID = ? ) Order by Name";
PREPARE stmt FROM #sqlQuery;
EXECUTE stmt #UserID, #UserID; -- here i passed same variable twice.
DEALLOCATE PREPARE stmt;
END;
In the above case I have to pass same variable (#UserID) twice, because it is used 2 times in my query. but this job is very hectic in long or complex query. so, how do I avoid this?
One another method I tried as follows:
CREATE PROCEDURE usp_MyProcedure (
IN UserID INT,
....
)
BEGIN
SET #UserID = UserID;
SET #sqlQuery = "SELECT Name From Users WHERE UserID > #UserID AND UserID IN ( SELECT UserID FROM OtherTable WHERE UserID = #UserID ) Order by Name";
PREPARE stmt FROM #sqlQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
But above query again does not cached. so, execution time is very long. and this type of variable declared as session global variable has may be conflict with another store procedure's variable. because I have call store procedure within this store procedure and variable name should be same in another store procedure.
So, let me know what is the best solution for the same.
Thanks.
Sorry just posted a mistaken one,
DELIMITER //
CREATE PROCEDURE yourprocedurenamehere(IN state CHAR(2))
BEGIN
SET #mystate = state;
SET #sql = CONCAT('SELECT * FROM BLABLABLA WHERE BLA = ?');
PREPARE stmt FROM #sql;
EXECUTE stmt USING #mystate;
END;
//
Sorry pal, just edited my code hahaha I got this wrong
A short answer is that there is no way to do it. In theory, you could identify prepared statement name with sha1(prepared statement query text), and use this as a statement handle. But there is no way to dynamically execute a statement which name is stored in a variable or in a table: EXECUTE itself is not allowed in Dynamic SQL query text.
A different question is whether you need a Dynamic SQL in your example at all, it seems like a standard SQL stored procedure parameterized with input parameters could do just fine.
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'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.