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;
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 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;
I want to select from a table where a field is in a given csv string passed to a stored proc.
What is the fastest way to do this? Should I insert the values into a temporary table and join to that? Or is there a way to do it with one statement?
Thanks
Did some searching around and found a great answer.:)
Use MySql's string function FIND_IN_SET.
Example use:
SET #csvStr = "val1,val2,val3";
SELECT Col1
FROM Table1
WHERE FIND_IN_SET(Col2, #csvStr) > 0;
I edited the current answer with the "New Answer" and "Old Answer" pointing out that the new answer opens up your system to a SQL Injection vulnerability.
NEW ANSWER -
Well you have to do something like this as given below.
I am assuming your csv string would be as given in variable #str below. Else you need to make sure that your string (or arraystring) should have this format with single quotes for every element -
set #str = "'some1','some2','some3'";
set #qry1 = CONCAT('select * from testing where col1 in (',#str,')');
prepare stmt1 from #qry1;
execute stmt1;
deallocate prepare stmt1;
OLD ANSWER -
I assume that you will pass the csv file path to stored proc and read the lines in csv in that stored proc. So basically you can store all those csv field values in a temp table and write query using IN -
select * from sourceTable
where fieldValue in (select csvFieldValue from #temptable)