I have a stored procedure which selects from a certain table. This table gets passed to the procedure as a parameter.
SELECT * FROM ParamName
And all it tells me when I try to run it is 'Table ParamName doesn't exist.
Any suggestions are greatly appreciated?
ParamName by itself would appear to MySQL as a table/field name, which it's rightly complaining about. If Paramname is a parameter for the stored procedure, you'd have to use #ParamName to tell MySQL to look for a variable of that name.
However, you can't simply do
SELECT * FROM #ParamName
mysql doesn't allow table/fieldnames to be specified via variables. You'll have to prepare a statement first:
SET #sql=CONCAT('SELECT * FROM ', #ParamName);
PREPARE s1 FROM #sql;
EXECUTE s1;
Related
I have a stored procedure which function to retrieve the ColumnProperty based on the input parameter matching the ColumnRule.
For example,
I will execute the below to get the ColumnProperty as string(short). But the problem is when using WHERE to filter ColumnRule, the retrieved value is string and get unknown type at the end.
CALL `testing-spGetColumnType`('varchar(11)', #outputProperty);
select #outputProperty;
DELIMITER $$
CREATE PROCEDURE `testing-spGetColumnType`(IN pColumnType varchar(50),OUT pColumnProperty varchar(50))
BEGIN
SELECT ColumnProperty FROM model_column_type where pColumnType like replace(ColumnRule, 'variable', pColumnType) into pColumnProperty;
SELECT IFNULL(pColumnProperty,'unknown type') into pColumnProperty;
END$$
DELIMITER ;
The sample table:
when the condition in the WHERE clause is evaluated against the stringShort row, given 'varchar(11)' as the argument, it's equivalent to
WHERE 'varchar(11)'
LIKE '%varchar% and SUBSTRING_INDEX(SUBSTRING_INDEX(varchar(11),''('',-1),'')'',1) < 50'
and the result of the LIKE comparison will be FALSE.
The value of ColumnRule from that row
%varchar% and SUBSTRING_INDEX(SUBSTRING_INDEX(variable,'(',-1),')',1) < 50
is a value. It doesn't matter that it looks like SQL text. In the context of the SELECT statement, it is just a string of characters. It's a string value. It is not references to identifiers, or SQL functions, or boolean operators.
We would get the same result if the ColumnRule value was
%varchar% one two buckle my shoe
To get a string value to be seen as SQL text, we can use dynamically prepared SQL.
In the context of MySQL PROCEDURE, we can dynamically create SQL text and store it as a string, and then execute the string, something like this:
SET #foo = ' foo, bar' ;
SET #sql = CONCAT('SELECT ',#foo,' FROM mytab',' ORDER BY ',#foo);
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
A word of caution: if we dynamically create SQL text, and incorporate potentially unsafe values, we can open a gaping SQL Injection vulnerability, ala Little Bobby Tables https://xkcd.com/327/
MySQL Reference https://dev.mysql.com/doc/refman/8.0/en/sql-syntax-prepared-statements.html
I have a stored procedure that is similar to below
SELECT *
FROM Table1
WHERE Tag IN (ids)
here Tag is an Integer column.
I tired to pass in comma separated values as string into the stored procedure but it does not work. Then I used stored procedure like below
SELECT *
FROM Table1
WHERE FIND_IN_SET(Tag, ids)
This works very well, the only problem is my table is very big - millions of rows and using FIND_IN_SET takes too long compared to IN when running a direct SQL statement.
What would be the best performance optimized option to use?
Is there a split function that can convert the ids into integer and parse it ready for IN clause? I think that would be the best option. Any suggestions or ideas?
You can prepare a statement and then execute it:
set #sql = concat('select * from table1 where tag in (', ids, ')');
PREPARE q FROM #sql;
execute q;
This constructs the string for each execution, so you can use in. The resulting execute should be able to use an index on tag, which should speed things up considerably.
This question already has answers here:
Parameterize an SQL IN clause
(41 answers)
Closed 9 years ago.
I have a stored procedure with one input parameter called "#IDs". This gets populated from my application which will populate it in the following format: '2, 30, 105'. The number of values inside this parameter will differ of course (For example: sometimes #IDs will be '100, 2005, 2, 510') My stored procedure is very simple. I have a table called "Persons". I'm trying to write this query:
Select * From Persons Where P_Id in (#IDs)
P_ID is the primary key in my table. The error I get is 'Conversion failed when converting the varchar value '2, 3, 4' to data type int.' Any suggestions will be greatly appreciated. Thanks.
One way is use dynamic SQL. That is generate the SQL as a string and then execute it.
An easier way (perhaps) is to use like:
where concat(', ', #IDS, ', ') like concat('%, ', id, ', %')
Note that this puts the separator at the beginning and end of the expressions, so "10" won't match "11010".
you might need to do a prepared statement. The idea is to build the select sentence and then execute it. Here's an example on how to do it...
USE mydb;
DROP PROCEDURE IF EXISTS execSql;
DELIMITER //
CREATE PROCEDURE execSql (
IN sqlq VARCHAR(5000)
) COMMENT 'Executes the statement'
BEGIN
SET #sqlv=concat(concat('select abc from yourtable where abc in (',sqll),')');
PREPARE stmt FROM #sqlv;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
Just change the query for the one you want to execute.
1) Show your code.
2) You've probably tried to pass in all the values as one parameter. That doesn't work. You have to list them as separate parameters and then bind them as separate parameters.
Yes, this makes it hard to use stored procedures when the number of in parameters may change.
I'm trying to rename a list of tables using a constant prefix defined as a #var:
SET #p='newprefix_';
RENAME TABLE `oldprefix_tablename1` TO CONCAT(#p, 'tablename1');
RENAME TABLE `oldprefix_tablename2` TO CONCAT(#p, 'tablename2');
This syntax is wrong, but I see that:
SELECT CONCAT(#p, 'tablename'); //outputs newprefix_tablename
What's the correct way/syntax to use here?
You can't do it directly the way you are trying. As the manual says (http://dev.mysql.com/doc/refman/5.1/en/user-variables.html)
User variables are intended to provide data values. They cannot be
used directly in an SQL statement as an identifier or as part of an
identifier, such as in contexts where a table or database name is
expected, or as a reserved word such as SELECT.
You have to use prepared statements:
SET #p = 'newprefix_';
SET #s = CONCAT('RENAME TABLE `oldprefix_tablename1` to ', #p, 'tablename1');
PREPARE stmt FROM #s;
EXECUTE stmt;
Im hoping someone will be able to help. I have created my first stored procdure (nothing fancy) however im running into an issue.
I want to give it a string input such as 1,2,3,4,5 then it does a simple SELECT * FROM [TABLE] WHERE EAN IN (VAR);
So the stored proc looks like this:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE PROCEDURE `moments`.`new_procedure`(IN var1 VARCHAR(255))
BEGIN
SELECT * FROM moments.PRODUCT WHERE EAN IN (var1);
END
Im am trying to execute it like such:
Works
call moments.new_procedure('5045318357397')
Does Not Work
call moments.new_procedure('5045318357397,5045318357427');
This executes but doesnt not bring back any results. Is it classing the second statement as a string so its doing this:
select * from moments.PRODUCT WHERE EAN IN ('5045318357397,5045318357427')
and not this:
select * from moments.PRODUCT WHERE EAN IN ('5045318357397','5045318357427')
How do i have to format the input in the execute query to get it to take a comma separated string as an input?
You could use:
SELECT * FROM moments.PRODUCT
WHERE FIND_IN_SET(EAN, var1)
This should work assuming it is actually comma delimited. Any other delimiting will not work in this case.
Assuming the string you passed is validated somehow and doesn't contain malicious sql, you can use prepared statements :
PREPARE stmt1 FROM CONCAT('select * from moments.PRODUCT WHERE EAN IN (',var1,')');
EXECUTE stmt1;