I've written a stored procedure function to get a name from a table. The trouble is that I want the table name to be passed in as a parameter (there are several different tables I need to use this function with):
DELIMITER $$
CREATE DEFINER=`root`#`localhost` FUNCTION `getName`(tableName VARCHAR(50), myId INT(11)) RETURNS VARCHAR(50)
begin
DECLARE myName VARCHAR(50);
SELECT
'name' INTO myName
FROM
tableName
WHERE
id=myId;
RETURN myName;
end
This method has an error because it uses the variable name "tableName" instead of the actual value of the variable.
I can work around this problem in a procedure by using a CONCAT like this:
SET #GetName = CONCAT("
SELECT
'name'
FROM
",tableName,"
WHERE
id=",myId,";
");
PREPARE stmt FROM #GetName;
EXECUTE stmt;
...but, when I try to do this in a function I get a message saying:
Dynamic SQL is not allowed in stored function or trigger
I tried to use a procedure instead, but I couldn't get it to just return a value, like a function does.
So, can anyone see a way to get around this problem. It seems incredibly basic really.
If you want to buld a SQL statement using identifiers, then you need to use prepared statements; but prepared statements cannot be used in functions. So, you can create a stored procedure with OUT parameter -
CREATE PROCEDURE getName
(IN tableName VARCHAR(50), IN myId INT(11), OUT myName VARCHAR(50))
BEGIN
SET #GetName =
CONCAT('SELECT name INTO #var1 FROM ', tableName, ' WHERE id=', myId);
PREPARE stmt FROM #GetName;
EXECUTE stmt;
SET myName = #var1;
END
Using example -
SET #tableName = 'tbl';
SET #myId = 1005;
SET #name = NULL;
CALL getName(#tableName, #myId, #name);
SELECT #name;
Related
DELIMITER $$
CREATE PROCEDURE prepared_return_value(IN columnName varchar(20), IN tableName varchar(20), IN rowIndex varchar(10))
BEGIN
SET #columnName = '';
SET #columnName = CONCAT('Select distinct ',columnName ,' from ', tableName, ' LIMIT ', rowIndex, ',', '1', ';');
-- SELECT #columnName;
PREPARE stmt FROM #columnName;
EXECUTE stmt;
END $$
DELIMITER ;
So, i'm trying to dynamic pivoting a table using prepared statements to return the unique value of the rows and use it to alter a table.
But for that, i need to be able to store the returned row value, so i can use it in another prepared statement as the column name.
Apparently i can't store the value from the execution of prepared statement neither from a procedure.
I've tried lot of things by know, but none seemed to work, só... any hint on that?
The Varoable is session bound, so you can be used after the procedure has run .
SELECT #columnName
direct after the running outside if the procedure.
another option s to use an OUT Parameter besides the IN
Ypu would run
CALL return_value(columnName, tableName, rowIndex, #columnName)
And the crete procedure wil look like
CREATE PROCEDURE prepared_return_value(IN columnName varchar(20), IN tableName varchar(20), IN rowIndex varchar(10), OUT myoutput TEXT
Still what you are doing is highly problematic as it could be used for sql injection, so you should white list colu,nname an Tablename
I am trying to create function inside MySQL to create several queries for example :
DELIMITER |
CREATE PROCEDURE queryBuilder(_tableName varchar(100))
BEGIN
SET #str_query = 'SET #countRows = 0;SELECT COUNT(*) INTO #countRows FROM';
SET #str_query = CONCAT(#str_query,_tableName, '; SELECT #countRows');
PREPARE stmt1 FROM #str_query;
EXECUTE stmt1;
END|
DELIMITER;
but it doesn't work? how can i change to work? I know i can create IF statement but i want something with more flexibility.
I think you need to declare that variable before you set it. (I also chose not to use a reserved word in MySQL, i.e. 'count')
Like this (truncated):
BEGIN
DECLARE rowCount INT;
SET rowCount = 0;
SELECT COUNT(*) INTO rowCount from _tableName;
RETURN rowCount;
...
See examples like this: http://www.mysqltutorial.org/mysql-stored-function/
Hope that helps
I am running a query in MySQL 5.6.11. I have created a following stored procedure
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `digital_audio_test_detail`(IN temp VARCHAR(50), IN temp2 VARCHAR(50))
BEGIN
SET #temp_query = CONCAT('SELECT * FROM ',temp);
SET #final_query = CONCAT(#temp_query,'WHERE', temp,'.unit_test_result_id =',temp2);
PREPARE stmt FROM #final_query;
EXECUTE stmt;
END
When I call this procedure in my query page, I get syntax error at its CALL. This is how I execute my queries.
SELECT unit_test_result.*, #temp1 := unit_test.name, #temp2 := unit_test_result.id
FROM unit_test_result, unit_test
WHERE unit_test_result.test_run_id = 2
AND unit_test.id = unit_test_result.unit_test_id;
CALL digital_audio_test_detail(#temp1, #temp2);
I have to pass two parameters to the procedure. When I create a procedure with only first parameter and CALL it one parameter, it executes fine. But When I do with two parameters I get syntax error. Need help. Thanks
SET #final_query = CONCAT(#temp_query,'WHERE', temp,'.unit_test_result_id =',temp2);
The string you are building is not a valid query.
Add space before and after WHERE, as in
SET #final_query = CONCAT(#temp_query,' WHERE ', temp,'.unit_test_result_id =',temp2);
I have a Table and Rows in table like below
CREATE TABLE Areas(AreaName VARCHAR(255),
PinCode VARCHAR(255))
INSERT INTO Areas(AreaName, PinCode)
VALUES('Teynampet', '6000018'),
('Ramapuram', '6000089'),
('TNagar', '6000017'),
('Mylapore', '6000014'),
('Gopalapuram', '6000087')
I Wrote a SQL Procedure as Below
DROP PROCEDURE IF EXISTS mp_test;
CREATE PROCEDURE mp_test(IN pArea VARCHAR(255))
BEGIN
SET #Query = 'SELECT PinCode FROM Areas';
IF pArea != ''
THEN
SET #City = CONCAT(' WHERE AreaName = ', pArea);
END IF;
SET #Query = CONCAT(#Query, #City);
PREPARE stmt FROM #Query;
EXECUTE stmt;
END
When I Call the Procedure
CALL mp_test('Teynampet');
When i Execute i am Not getting the Desired result i.e is 600018
How can i build query dynamically in SP
Thanks for the Help
You're concatenating the pArea parameter into the SQL unquoted. That is, the content of #Query that you prepare for execution is:
SELECT PinCode FROM Areas WHERE AreaName = Teynampet
Since Teynampet is unquoted, it is parsed as a(n unknown) SQL identifier rather than a string. You should either:
quote it in your SQL:
SET #City = CONCAT(' WHERE AreaName = ', QUOTE(pArea));
pass it to the prepared statement as a parameter:
SET #City = CONCAT(' WHERE AreaName = ?');
SET #param = pArea;
and then:
EXECUTE stmt USING #param;
However, why use prepared statements here? Your procedure can be rewritten as a simple SELECT (which raises the question of whether you need to use a stored procedure at all):
CREATE PROCEDURE mp_test(IN pArea VARCHAR(255))
SELECT PinCode FROM Areas WHERE pArea IN (AreaName, '');
(Note that I'd recommend you use NULL instead of the empty string '', in which case the above test would be pArea IS NULL OR pArea = AreaName).
I've written a stored procedure. It's working fine except taking the table name as input parameter.
Let see my proc in MySQL:
DELIMITER $$
USE `db_test`$$
DROP PROCEDURE IF EXISTS test_proc$$
CREATE DEFINER=`root`#`localhost`
PROCEDURE `test_proc`(IN serviceName VARCHAR(10),IN newsInfoTable VARCHAR(100))
BEGIN
SELECT COUNT(*) FROM newsInfoTable WHERE newsServiceName=serviceName;
END$$
DELIMITER ;
Stored procedure calling parameters:
USE db_test;
CALL test_proc('abc','tbl_test_news');
Here the service name parameter is working fine. But if I include the newsInfoTable variable as table input parameter then a error shows.
Table 'db_test.newsinfotable' doesn't exist
Why does this happen only for table parameter? How can I retrieve from this error or
How I pass a table name into a stored procedure as a parameter?
An SP cannot be optimized with a dynamic table name, so many DBs, MySQL included, don't allow table names to be specified dynamically.
One way around this is to use Dynamic SQL.
CREATE DEFINER=`root`#`localhost` PROCEDURE `test_proc`(IN serviceName VARCHAR(10),IN newsInfoTable VARCHAR(100))
BEGIN
SET #sql = CONCAT('SELECT COUNT(*) FROM ',newsInfoTable,' WHERE newsServiceName=?;');
PREPARE s1 from #sql;
SET #paramA = serviceName;
EXECUTE s1 USING #paramA;
END$$
You can use EXECUTE IMMEDIATE for a "less is more" solution (for me, less code = good)
CREATE PROCEDURE test_proc(IN serviceName VARCHAR(10), IN newsInfoTable VARCHAR(100))
BEGIN
EXECUTE IMMEDIATE CONCAT('SELECT COUNT(*) FROM ',newsInfoTable,' WHERE newsServiceName=''', serviceName, '''');
END
that part of a query cannot be dynamic.
you may consider implementing as a string that is executed dynamically at runtime
Although may not be what you want, alternatively, can consider to use conditionally if and prepare the statement.
DELIMITER $$
CREATE PROCEDURE select_count(IN table_name VARCHAR(20))
BEGIN
IF table_name = 'xxx' THEN
SELECT * FROM xxx;
ELSEIF table_name = 'yyy' THEN
...
ENDIF
END$$