I am trying to create a stored procedure to change the name of an existing table by appending the date to it.
I have only been using MySQL for a short while and cannot see why the code is not working. I'm using MySQL Workbench 8.0 Community to connect to the MySQL database and run the code. In Workbench no errors are returned when I run the code.
The code I have managed to find so far is:
DELIMITER \\
DROP PROCEDURE IF EXISTS `usp_test_dynamic_sql`\\
CREATE PROCEDURE `usp_test_dynamic_sql`()
BEGIN
SET #s = concat('ALTER TABLE MyDashboardTable RENAME TO MyDashboardTable_',replace(date(now()),'-',''));
PREPARE stmt1 FROM #s;
EXECUTE stmt1;
END\\
DELIMITER ;
I have run part of the code, to find what #s is being set to by running:
SET #s = concat('ALTER TABLE MyDashboardTable RENAME TO MyDashboardTable_',replace(date(now()),'-',''));
select #s;
I have then pasted the result for #s
ALTER TABLE MyDashboardTable RENAME TO MyDashboardTable_20200904
This does change the name of the table but I cannot figure out why the stored procedure does not. Any help will be greatly appreciated.
Execute your SP as
CALL usp_test_dynamic_sql();
You may also want to modify your
replace(date(now()),'-','')
with
DATE_FORMAT(NOW(),'%Y%m%d')
Even though it's not absolutely necessary. If you do, do not leave spaces or use '-' or '/' between the formats since MySQL with throw an error.
Related
I already wrote a pretty complex stored procedure, but now i want to bring some dynamics into the procedures using variables. I still call myself a newbiew when it comes to sql programming, so i might be totally on the wrong way with what i'd like to achieve.
I am running the latest MySQL server 8.0.13 on windows (just for local dev).
My current idea for the stored procedure
... uses an input variable
... declares a cursor (using the var)
... create a temp table (using the var)
... iterates through the temp table
... write data to a new table
I think i understand some of the basic tools to do that but i fail again and again with handling the variable(s)
The following code shows the top part of the project where i already fail.
PROCEDURE sprProcedure (
IN vInputParameter varchar(64)
)
BEGIN
DECLARE vFinished INTEGER DEFAULT 0;
-- declare cursor
DECLARE cCursor CURSOR FOR SELECT * FROM tbltmp_(vInputParameter);
DECLARE CONTINUE HANDLER
FOR NOT FOUND SET vFinished = 1;
-- drop / create temp table
DROP TABLE IF EXISTS (vInputParameter);
CREATE TEMPORARY TABLE tbltmp_(vInputParameter)
SELECT * FROM `tbl_DataSource`;
... did not paste any further code as i can't deal with the following issue.
I tried
... using the variable directly > variable is not resolved in DECLARE CURSOR statement
... define user-defined variable before local-variables is not allowed
... CONCAT'ed the string to build a statement and EXECUTE'ed it > does not work in the DECLAREpart of the stored procedure
At this point i am totally open to every hint or totally new ideas about how to approach this.
Thanks for any advice!
[Update]
My approach up there has some flaws and i did not understand the basic concept of temp tables for example being unique to the session. Thanks to 'D's Query' and a little more reading i now have a working stored procedure without having to deal with dynamic names of cursors and temp tables.
I dont know what actually you are focusing on but loading a dynamic tables can be possible with prepared statements in Stored Procedures but prepared statements won't work with CURSORS.
Example of Prepared statement is
SET $sql=CONCAT('SELECT * from ', var_tablename);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I'm interested in creating a trigger that will write a file after I import a csv into my table. The file name includes a time stamp and my code isn't working properly. Here's what I have so far.
DELIMITER $$
CREATE TRIGGER peachtree_trigger
AFTER INSERT ON peachtree
FOR EACH ROW
BEGIN
SET #sql_text = CONCAT("SELECT * FROM peachtree
INTO OUTFILE '/srv/samba/share/peachtree_",
DATE_FORMAT(NOW(), '%Y_%m_%D'), ".csv'");
PREPARE s1 FROM #sql_text;
EXECUTE s1;
DROP PREPARE s1;
END $$ DELIMITER ;
The set statement works fine outside of the trigger. However when I execute the above set of code and then try SHOW TRIGGERS IN test; it returns an empty set. If anyone could help I would be very grateful.
from http://dev.mysql.com/doc/refman/5.5/en/stored-program-restrictions.html
<snip>
SQL prepared statements (PREPARE, EXECUTE, DEALLOCATE PREPARE) can be used in stored procedures, but not stored functions or triggers. Thus, stored functions and triggers cannot use dynamic SQL (where you construct statements as strings and then execute them).
</snip>
Can a stored procedure plus a sql query be executed from within a trigger?
procedure plus query
SET #tmp = (SELECT fvalue FROM ftable WHERE id=2);
SET #SQL = CONCAT('INSERT INTO ',#tmp,' VALUES (''buhambug'')');
PREPARE stmt FROM #SQL;
EXECUTE stmt;
If so what are the rules and links to examples? I have't been able to find any.
Yeah, you can call a stored procedure from a trigger like this:
Create trigger foo after insert on table for each row
BEGIN
call your_procedure(params);
END$$
Note the ending delimiter. If ; is the default delimiter inside the trigger as well, then it won't work, for MySQL will treat each command separately and throw error. You want the entire code inside the trigger to be executed together. hence declare a different delimiter, like $$ prior to defining the trigger, through Delimiter $$. Then, ; will work correctly inside the the trigger. After you terminate the trigger through $$, don't forget to restore the default delimiter.
I learned today through this section of the MySQL documentation that prepared statements cannot be performed in stored functions, but, as of MySQL version 5.0.13, they can be performed in stored procedures.
Today I was putting together a stored procedure and thought initially it might be interesting to try doing an INSERT statement in it as a prepared statement. However, despite this supposedly being possible (I'm using MySQL 5.5.14), the ? parameter marker in the statement string caused MySQL to throw a syntax error.
I threw a couple of simplified examples together using the same exact sort of syntax I used for the prepared INSERT statement. I'm hoping I just have a syntax error somewhere I just haven't caught. The first block, below, is the procedure that works, i.e. it uses the standard CONCAT(your query string) syntax.
DROP PROCEDURE IF EXISTS TestConc;
DELIMITER $$
CREATE Procedure TestConc()
BEGIN
SET #sql := CONCAT('CREATE TABLE Foo (FooID INT) ENGINE = InnoDB');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #tn := 'Foo';
SET #sql := CONCAT('INSERT INTO ', #tn, ' VALUES (5)');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
$$
DELIMITER ;
Upon calling the procedure with this code, the expected happens; 5 is stored in the FooID field of the newly-generated Foo table. However, if we change the lines between the two DEALLOCATE PREPARE directives to this:
SET #tn := 'Foo';
SET #sql := 'INSERT INTO ? VALUES (5)';
PREPARE stmt FROM #sql;
EXECUTE stmt USING #tn;
We get an error that tells us to check the syntax of the statement near '? VALUES (5)'.
Is it just not possible to substitute a parameter marker for a table name? I haven't tried doing something along the lines of 'SELECT ? FROM Foo' to see if this will work yet. Also, and I don't know if it's important, I've been trying this using MySQL Workbench 5.2.35 CE, rather than a command line.
I don't have any specific need to run queries as prepared statements within procedures ATM, I just want to make sure I have the syntax correct for doing so if I ever should need to.
The parameter '?' cannot be used for identifiers. Use first variant. From the reference - Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth.
Is it just not possible to substitute a parameter marker for a table name?
No, it's not possible. If you ever think you need this feature, it could be a sign that you have a bad table design.
If you really need to specify the table at runtime, you can use dynamic SQL but be careful not to introduce SQL injection vulnerabilities.
Is there a way to programmatically create stored procedures using MySQL? I can write a stored procedure to create databases and tables using prepared statements, but I get an error message saying it is not supported to create stored procedures with prepared statements.
I realize I can do this in PHP or Java, but so far I have been keeping all my schema management tools as SQL scripts, and I would like to avoid a second language dependency if I can.
One method you can try is to build the create procedure statement dynamically in SQL, then use select into outfile to dump the statement to local disk, and then source the file to load the procedure into the DB.
Here's a quick example:
set #proc_name = 'my_proc';
set #body1 = 'select ''hello''; ';
set #body2 = 'select ''world''; ';
set #delimiter = '$$';
set #create_proc_stmt = concat(
'create procedure ',
#proc_name,
'() begin ',
#body1,
#body2,
' end ',
#delimiter
);
select #create_proc_stmt into outfile '/tmp/create_proc_stmt.sql';
delimiter $$
\. /tmp/create_proc_stmt.sql
delimiter ;
call my_proc();
I think you can do it by inserting a record into INFORMATION_SCHEMA.ROUTINES table. I haven't tried it, but it should work (one day in the past I forgot to add --routines switch to mysqldump, and later I restored all procedures by dumping this one table).