Procedure to USE dynamic database name on Multi Table Delete - mysql

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 :-/

Related

Error Executing This Mysql Sp For Make Refresh Of The Fields Saved In Log Table Through Trigger But I Don't See The Error

This sp generate this Error but when I get the #queryString value and execute it, It's working:
Query 1 ERROR: 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 'CREATE TRIGGER triggers_after_insert AFTER INSERT ON mydb.mytable F' at line 2
This error is generated when I execute:
CALL prcTriggersLogsRefreshFields('mydb','mytable','myidtable');
This is the code:
DROP PROCEDURE "prcTriggersLogsRefreshFields";
CREATE PROCEDURE "prcTriggersLogsRefreshFields"(
par_dbName text,
par_tableName text,
par_keyField text
)
BEGIN
SET #strJsonObj = null;
SET #change_object = par_dbName||'.'||par_tableName;
SELECT GROUP_CONCAT('\'',COLUMN_NAME, '\',', COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = par_dbName AND TABLE_NAME = par_tableName INTO #strJsonObj;
SET #queryString = 'DROP TRIGGER `triggers_after_insert`;
CREATE TRIGGER `triggers_after_insert` AFTER INSERT ON `'||par_dbName||'`.`'||par_tableName||'` FOR EACH ROW BEGIN
SELECT JSON_ARRAYAGG(JSON_OBJECT('||#strJsonObj||')) change_obj FROM `'||par_dbName||'`.`'||par_tableName||'` WHERE '||par_keyField||'=New.'||par_keyField||' INTO #jsonRow;
INSERT INTO mylog_db.table_log (`change_id`, `change_date`, `db_name`, `table_name`, `change_object`, `change_event_name`, `previous_content`, `change_content`, `change_user`) VALUES (DEFAULT, NOW(), '''||par_dbName||''', '''||par_tableName||''', '''||#change_object||''', \'insert\', \'{}\', #jsonRow, New.user_created);
END;';
-- select #queryString;
PREPARE stmt FROM #queryString;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html says:
SQL syntax for prepared statements does not support multi-statements (that is, multiple statements within a single string separated by ; characters).
You have to run the statements one at a time if you use PREPARE.
There's no need to include the DROP TRIGGER in your prepared statement. You can run the DROP TRIGGER without prepare & execute, since there is no dynamic part in it. Then format the CREATE TRIGGER as a single statement and prepare and execute it.

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')

Execute multiple semi-colon separated query using mysql Prepared Statement

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

syntax error with concat and limit in mysql

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);

How to run mysql queries that are stored in a mysql table using a procedure

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