prepare statement-What is the problem here - mysql

DELIMITER $$
CREATE PROCEDURE `Insert1`(IN NAME VARCHAR(100),IN valuees VARCHAR(100))
BEGIN
SET #r = CONCAT('Insert into', NAME,'(name)','VALUES',valuees);
PREPARE smpt FROM #r;
EXECUTE smpt;
DEALLOCATE PREPARE smpt;
END$$
DELIMITER ;
it is successfully compiling...
but when i execute gives me problem...
**CALL Insert1('rishi','duyuu')**
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 'VALUESduyuu' at line 1

There are multiple problems, first see what query has the CONCAT function produced. You will notice that it's not a valid query - 'Insert intorishi(name)VALUESduyuu'. Next, see the documentation on PREPARE/EXECUTE and use a placeholder for the value. The string would need to be put into quotes and escaped if you want to produce a raw query string. So try something like this:
SET #r = CONCAT('INSERT INTO ', NAME, ' (name) VALUES (?)');
SET #v = valuees;
PREPARE smpt FROM #r;
EXECUTE smpt USING #v;
Btw, instead of asking a number of small questions here, maybe you should ask a more high level question, explain what you have tried, what failed, etc. It's easier to help you with high level issues, but if you are doing something the wrong way and ask small technical questions how to fix it so that it works the wrong way, it won't help you much.

Add spaces to the concatenation:
CONCAT('Insert into ', NAME,'(name)',' VALUES ',valuees);

Related

Cant create procedure in MySql 5.7

I'm racking my head, I can't figure out what the problem is. This SQL code does not work on MySQL 5.7
CREATE PROCEDURE sp_create_message (queue_name VARCHAR(50), data TEXT)
DETERMINISTIC
BEGIN
SET #stm = CONCAT('
INSERT INTO queue_', queue_name, '
(data)
VALUES
(?)
');
PREPARE stm FROM #stm;
EXECUTE stm USING data;
DEALLOCATE PREPARE stm;
END //
#1064 - You have an error in the request. Check the documentation for the MySQL version you are using for the correct syntax about " on line 4
i dont now whats the problem.
Rather than use the value directly from an input parameter,the USING clause in the EXECUTE statement only accept user variables. Try modify the code like this:
set #data=data;
EXECUTE stm USING #data;

MySql prepare statement - is it possible to parametrize column name or function name?

Lets say that I want to write a procedure allowing me to call certain function on certain column, for example:
call foo('min','age') -> SELECT min(age) FROM table;
I want my procedure to be safe from sql injection, therefore, I'm willing to use prepared statements and parametrize the input
SET #var = "SELECT ?(?) FROM table;"
PREPARE x FROM #var;
EXECUTE x USING a, b;
Where a and b are input parameters, function and column, respectively.
However, it doesnt seem to be possible - InnoDB keeps throwing an error whenever I want to execute this statement.
Is it possible to solve this this way, or I need to resort to whitelisting?
EDIT:
Full code:
create procedure test(in func varchar(20), in col varchar(20))
begin
set #f = func;
set #c = col;
set #sql = "select ?(?) from table;";
prepare x from #sql;
execute x using #f, #c;
end;
calling:
call test('min','age');
Full error:
[42000][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 '(?) from table' at line 1
You cannot parametrize column/table/function name/alias. As, PREPARE statement only allow "values" part of the SQL query to be used as parameters. Function/Table/Column name/alias are used to determine the validity of the SQL statement; and thus cannot be changed during run-time execution. Changing it at execution time would potentially alter whether the SQL statement was valid.
You can think of it as compiling a code; hence the compiler must know all the function/class name(s) etc for creating a valid executable (yes, we can do dynamic classes, but that is rare). On the other hand, we can change input "values" to the program, but generally cannot change the operations to be done on the input data.
Also, MySQL server would consider the parameters as literals, and apply quotes around them, before using them in query execution.
Now, in your case, you can still use the function name as parameter for Stored procedure, and generate the query string using that. But you cannot use it as a parameter for the query itself.
delimiter $$
create procedure test(in func varchar(20), in col varchar(20))
begin
set #c = col;
-- use concat function to generate the query string using func parameter
set #sql = concat('select ', func, '(?) from table');
-- prepare the statement
prepare stmt from #sql;
-- execute
execute x using #c;
-- don't forget to deallocate the prepared statement
deallocate prepare stmt;
end$$
delimiter ;
I came across this while writing a mySQL query builder plugin. My solution was to prefix column and function names with a "?" character (the user can change the character in the plugin preferences).
The code that builds the prepared statement looks for values that begin with "?" and inserts the subsequent column/function name into the query inline instead of as prepared statement values.

Database name as variable in MySQL query

I am creating a MySQL dump file, that needs to run with multiple databases.
The structure is almost like this :
SET #parent_database = 'db_name';
CREATE OR REPLACE VIEW t_colours AS
SELECT `key_name`, `value`
FROM #parent_database. `colours` as COLOURS WHERE 1;
When I run this query next time, my plan is to only change the variable parent_database.
Is this possible?
Everytime now I run this, I receive an error :
#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 '#parent_database.`colours` as COLOURS WHERE 1' at line 1
Any way to make this happen?
There are many more views to create.
When you execute the queries the mysql thinks of table names as objects and not as string, and hence this would not work as you would expect.
However, there is a way out and you could use something similar to below snippet.
SET #parent_database = 'db_name';
SET #q = CONCAT('CREATE OR REPLACE VIEW t_colours AS SELECT `key_name`,`value` FROM', #parent_database, '.`colours` as COLOURS WHERE 1;');
PREPARE stmt FROM #q;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

In mysql dynamic stored proc, is #var required to build a prepared statement?

I have a similar stored proc (but longer). It is called from PHP (GET request on Apache)
delimiter //
CREATE PROCEDURE dynamic(IN tbl CHAR(64), IN col CHAR(64))
BEGIN
SET #full_statement = CONCAT('SELECT ',col,' FROM ',tbl );
PREPARE stmt FROM #full_statement;
EXECUTE stmt;
END
//
delimiter ;
From what I read, #s is a mysql session variable living as long as my session is alive.
The #s presence annoys me since I fear that 2 concurrent request on that stored
proc might play with this "global variable". So I tried to remove the '#' like this
delimiter //
CREATE PROCEDURE dynamic(IN tbl CHAR(64), IN col CHAR(64))
BEGIN
DECLARE full_statement VARCHAR(300);
SET full_statement = CONCAT('SELECT ',col,' FROM ',tbl );
PREPARE stmt FROM full_statement;
EXECUTE stmt;
END
//
delimiter ;
to build the prepared statement without success.
I seem to have constantly
ERROR 1064 (42000): 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 'full_statement; EXECUTE stmt;
Does my fear of 2 calls within my php session is really a problem ?
(If not, what about having 200 stored procedures using that same
global variable) ?
Can I really achieve my goal and remove the '#' and let the prepared
statement being handle by a simple stored proc variable or is it a constraint of prepared statement ?
Regards.
Yes, the #var is required.
MySQL's PREPARE statement only accepts "user variables" (those prefixed with #), not local variables declared in a stored routine.
This has long been recognized as a WTF in MySQL:
Bug #17409 PREPARE doesn't support queries in local variables
Does my fear of 2 calls within my php session is really a problem ?
No. It's not a global variable, it's a session variable.
Two concurrent sessions have their own value for #var.

mysql stored procedure oddity

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.