I wanna know how to get field value from dynamic query. I do it on stored-procedure in MySQL. I've the following code:
...
DECLARE l_query VARCHAR(500);
DECLARE l_table VARCHAR(50);
SET l_table = 'tb_user';
SET #l_query = concat('SELECT count(1) FROM ', l_table);
-- #Note that l_table will not always for tb_user,
-- it can be changed with other table name.
PREPARE l_sql FROM #l_query;
EXECUTE l_sql;
...
The question is, how to get value for count result (count(1)) ..? I need this value, because it will be used on the next process at the same stored procedure.
Many thanks before.
Short: Use SELECT INTO to select the value into variable.
In your case:
...
DECLARE l_query VARCHAR(500);
DECLARE l_table VARCHAR(50);
DECLARE cnt INTEGER;
SET l_table = 'tb_user';
SET #l_query = concat('SELECT count(1) INTO #cnt FROM ', l_table);
-- #Note that l_table will not always for tb_user,
-- it can be changed with other table name.
PREPARE l_sql FROM #l_query;
EXECUTE l_sql;
-- Use cnt variable here
...
Related
Using MYSQL, how can I select a table whose name has been stored as a variable? For instance, I have 2 tables (T1 and T2) and I want to derive T3:
DECLARE i INT; DECLARE n INT;
DECLARE o VARCHAR(50);
DECLARE T3 VARCHAR(50);
SET n=(SELECT COUNT(*) FROM `T1`);
i=1
WHILE i<n+1 DO
SET o=(SELECT customer FROM `T1` WHERE IDligne=i);
SET T3=(SELECT MiddleCat FROM `T2` WHERE customer=o);
SET x = SELECT * FROM `T3`;
SET i=i+1;
END WHILE;
END
I want to set the variable (x) to be equal to the result of the T3 query (to retrieve the name of other tables):
But this shows an error. What query should I used instead?
You should use a prepared statement. You can use a session variable to store the result of your query. In the example below, I assign the result of a count query into a variable #result.
DECLARE #query VARCHAR(50);
SET #result := 0;
SET T3 = (SELECT MiddleCat FROM `T2` WHERE customer=o);
SET #query = CONCAT('SELECT COUNT(*) INTO #result FROM ', T3);
PREPARE stmt FROM #query;
EXECUTE stmt;
Highly relevant: Using select into local variable and prepared statement in mysql
Simply in your case you can user either of the following :
1. Print T3
2. Select T3
I want add values to multiple columns
ALTER PROCEDURE DynamicInsertQuery
#ColumnName VARCHAR(MAX),
#RiD VARCHAR(50)
AS
BEGIN
DECLARE #DynamicQuery NVARCHAR(MAX)
SET #DynamicQuery = 'UPDATE tbl_route_info SET ('+ #ColumnName +') = (1) WHERE RouteId=('+#RiD+')'
EXEC(#DynamicQuery)
END
This is the code I tried.
I run this procedure like this
DynamicInsertQuery '(1,2)','10'
I suspect you want something like this:
ALTER PROCEDURE DynamicInsertQuery (
#ColumnName VARCHAR(MAX),
#RiD VARCHAR(50)
) AS
BEGIN
DECLARE #DynamicQuery NVARCHAR(MAX);
SET #DynamicQuery = 'update tbl_route_into set #ColumnName = 1 where RouteId = #RiD';
SET #DynamicQuery = REPLACE(#DynamicQuery, '#ColumnName', #ColumnName);
EXEC sp_executesql #DynamicQuery, N'#RiD VARCHAR(50)', #RiD = #RiD;
END;
Notes:
You have too many parentheses in your version.
If you are learning to use dynamic SQL, then learn sp_executesql -- and how to use it to pass parameters.
You cannot pass names of things (columns, tables, etc.) as parameters, so that has to be placed directly in the string.
You can pass values into the string, such as #RiD.
I have below set statements for MSSQL, which works perfect :
Declare #uid INT;
Declare #ct int;
Declare #code int;
Declare #usertype int;
Declare #flag char;
Declare #max_itemid int;
Declare #ulname varchar(10);
Declare #ufname varchar(10);
set #code= 123;
set #ulname='Will';
set #ufname='Smith';
set #max_itemid=(select max(itemid) from registration;
set #uid = (select uid from users where ulname=#ulname and ufname=#ufname)
set #ct=(select count(*) from usercodes where itemId=#uid)
set #usertype=(select usertype from users where uid=#uid)
If(#usertype=1)
begin
If (#uid>0)
Begin
select * from users where uid=#uid;
select * from usercodes where itemId=#uid;
if(#ct=0)
begin
if (#max_itemid=2 or #max_itemid=0)
set #flag='D';
else
set #flag='O';
insert into usercodes (itemId,CODE,Flag) values(#uid,#code,#flag);
select * from usercodes where itemId=#uid;
else
begin
PRINT 'UserCode is already added and below is result:';
select * from usercodes where itemId=#uid;
end
end
Else
PRINT 'No User Found';
end
else
begin
print 'User not added as usertype is ';PRINT #usertype;
end
Now i am a newbee to Mysql and want to rewrite the above statements as per the Mysql conventions. I figured out the syntax, and changes the declarations as :
SET #CODE='S10_12345' ;
SET #NAME='Will Smith';
and so on.
But the executions stops once it enters the IF statement. Can someone help figuring out where I am wrong ?
P.S. I am not using any procedures/functions - i can't store these bunch of statements as I have to customize the select statements as the DB can change each time.
Column name set in stored procedure but not working. But when I run this script empty rows appears. What I do this for run this script?
Create Procedure Test
()
AS
BEGIN
Declare #columnName nvarchar(50);
set #columnName ='StoreName';
SELECT *
FROM testtable
WHERE #columnName = 'storemanager'
END
You need to use dynamic SQL because you can't reference a column with a variable - T-SQL just doesn't parse things in that order. Try something like:
CREATE PROCEDURE dbo.Test
#columnName NVARCHAR(50),
#value NVARCHAR(4000)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT * FROM dbo.testtable WHERE '
+ QUOTENAME(#columnName) + ' = #value;';
EXEC sp_executesql #sql, N'#value NVARCHAR(4000)', #value;
END
GO
QUOTENAME() wraps the column in [square brackets] and hopefully protects you from SQL injection. You should also read these posts:
Bad habits to kick : using SELECT * / omitting the column list
Bad habits to kick : avoiding the schema prefix
My stored procedure "best practices" checklist
I have this:
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_name = 'whatever'
but what I need is something like this:
SELECT TABLE_NAME, COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE column_data = 'whatever'
So, in words, I have a value and I have no idea where it's stored. Is there a way to literally check the entire database and return the table, column?
aaaand yes, I know, db admins wouldn't be happy!
This might get you going in the right direction.
1. Create find_column stored procedure
DROP PROCEDURE IF EXISTS `find_column`;
DELIMITER $$
CREATE PROCEDURE `find_column`(IN i_value varchar(200),
OUT o_columns varchar(2000),
OUT o_message varchar(500))
MAIN_BLOCK : BEGIN
DECLARE is_numeric boolean;
CHECK_NUMERIC : BEGIN
set is_numeric = i_value REGEXP '^(-|\\+){0,1}([0-9]+\\.[0-9]*|[0-9]*\\.[0-9]+|[0-9]+)$';
END CHECK_NUMERIC;
FIND_IT : BEGIN
DECLARE bNoMoreRows BOOLEAN DEFAULT FALSE;
DECLARE v_schema varchar(64);
DECLARE v_table varchar(64);
DECLARE v_column varchar(64);
DECLARE v_data_type varchar(64);
DECLARE v_count int;
-- all schemas, tables and columns in DB
DECLARE columns CURSOR FOR
select table_schema,table_name,column_name,data_type from information_schema.columns;
DECLARE EXIT HANDLER for SQLEXCEPTION set o_message := concat('Unexpected error while trying to find schema, table and column for value : ',i_value);
declare continue handler for not found set bNoMoreRows := true;
open columns;
set o_columns = "";
COLUMN_LOOP: loop
fetch columns
into v_schema,v_table,v_column,v_data_type;
if (
(v_data_type in ('int','bigint','tinyint','decimal','smallint','mediumint') and is_numeric=1)
or (v_data_type not in ('int','bigint','tinyint','decimal','smallint','mediumint') and is_numeric=0)
)
then
SET #dyn_sql=CONCAT('select count(*) into #c from `',v_schema,'`.`',v_table,'` where `',v_column,'`=?');
SET #c = 0;
SET #v_value = i_value;
PREPARE stmt FROM #dyn_sql;
EXECUTE stmt using #v_value;
DEALLOCATE PREPARE stmt;
SET v_count = #c;
if v_count > 0 then
if length(o_columns <= 1800) then
set o_columns = concat(o_columns,",",v_schema,".",v_table,".",v_column);
end if;
end if;
end if;
if bNoMoreRows then
set o_columns = substring(o_columns,2);
close columns;
leave COLUMN_LOOP;
end if;
END loop COLUMN_LOOP;
END FIND_IT;
END MAIN_BLOCK$$
DELIMITER ;
2. Call find_column stored procedure with your value
call `find_column`('whatever',#columns,#message);
3. Check out the results
select #columns;
The is_numeric bit is lovingly ripped-off JBB's answer from this post.
It ain't perfect (what happens if the number of columns that your value exists exceeds 10 or so? If that is the case then this will only return the first 10 or so columns (depends on how long the schema.table.column name string is).
Hopefully it'll get you going in the correct direction.
An you're right. You're DB admins will be unhappy with you. But if you don't annoy them once in a while then you're not trying hard enough IMHO ;-)
Good luck.