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
Related
I need to create a 'select' mysql procedure that will accept multiple parameters, inline with this the procedure will select to other tables
Objective
Stored procedure must accept multiple parameters
Using the multiple parameters, procedure should select on table_a, table_b and table_c
Currently i am using this code (it accepts multiple parameter but I don't know how to modify it so it would do another select on table_b and table_c)
DELIMITER //
CREATE PROCEDURE select_multiple_object(IN user_ids VARCHAR(65535))
BEGIN
SET #query = CONCAT ('SELECt * FROM table_a WHERE userid IN (',user_ids,')');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
What I really want to achieve is something like this:
DELIMITER //
CREATE PROCEDURE select_multiple_object(IN user_ids VARCHAR(65535))
BEGIN
SET #query = CONCAT ('
SELECt * FROM table_a WHERE userid IN (',user_ids,');
SELECt * FROM table_b WHERE userid IN (',user_ids,');
SELECt * FROM table_c WHERE userid IN (',user_ids,');
');
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
CALL select_multiple_object('1,2,3')
Assemble your MySQL query first, then send the query, similar to the following:
$parameter = "user_ids";
$table = "table_a";
$query = 'SELECT * FROM ' . $parameter . ' WHERE userid IN (",' . $parameter . ',")';
$result = mysql_query($query);
To input multiple parameters, simply use a loop to repeat this process as needed.
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')
I'm trying to make a procedure for MySQL 5.1 that will take a database name as an argument and issue a MULTI DELETE inside that database. I'm running into two problems that I'm not sure how to work around:
USE can't be used in a prepared statement. When I try, I get "This command is not supported in the prepared statement protocol yet".
MULTI DELETEs can't delete a table in a different database. When I try, I get "Unknown table 'x' in MULTI DELETE".
A code sample is as follows:
DELIMITER $$
CREATE PROCEDURE multi_test (
IN dbname VARCHAR(20)
)
BEGIN
SET #us = CONCAT('USE ', dbname, ';');
PREPARE ustmt FROM #us;
EXECUTE ustmt;
DEALLOCATE PREPARE ustmt;
SET #s = CONCAT('DELETE t FROM ', dbname, '.t as t INNER JOIN ', dbname, '.t2 as t2 IN t.f_id = t2.id');
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
Again, this results in "This command is not supported in the prepared statement protocol yet".
One other objective is to keep this in MySQL - I'd rather not use a scripting language that connects to MySQL, but rather just have some MySQL procedure that I can call from a client CLI. However, I'm not opposed to having procedures in other languages (like you can do in PostgreSQL) if that's possible in MySQL.
It appears I need to use the dbname and the table ALIAS when trying to use a MULTI DELETE.
DELETE dbname.talias FROM dbname.t as talias INNER JOIN dbname.t2 as t2 ON talias.f_id = t2.id
I believe I had tried that and it failed, but it now appears to be working :-/
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 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;