Is there a way to apply ROUND function for entire select statement in MYSQL instead of using it for every column?
I want to avoid repeating ROUND
SELECT
ROUND(col_1,2),
ROUND(col_2, 2),
ROUND(col_3,2)
FROM
TABLE_NAME
Could not find anything related in documentation.
If you mean to avoid repetition in code, here is a trick for 100 columns:
SET #q = 'SELECT ';
SET #i = 0;
WHILE #i < 100 DO
SET #q = CONCAT(#q, 'ROUND(col_',#i,',2), ');
SET #i = #i + 1;
END WHILE;
SET #q = CONCAT(SubStr(#q, 1, LENGTH(#q) - 2),' FROM TABLE_NAME');
PREPARE stmt FROM #q;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
You need to put it on a procedure and then call it.
Related
SET myvar = MONTHNAME(NOW());
SET #q = CONCAT('Insert into sales', myvar,'customer values (1000, ABC);','Insert into sales', myvar,'customer values (2000, XYZ);');
PREPARE QUERY from #q;
EXECUTE QUERY;
END //
How can we pass variable value as column name into query and concat multiple queries ?
You must have a valid INSERT INTO query with placeholders, and run the code as many times as you need.
This can be used in a loop with a cursor and much more:
DELIMITER $$
CREATE PROCEDURE mytest()
BEGIN
SET myvar = MONTHNAME(NOW());
SET #q = CONCAT('Insert into sales (', myvar,'customer) values (?, ?);');
PREPARE QUERY from #q;
SET #a = 1000;
SET #b = "ABC";
EXECUTE QUERY USING #a, #b;
SET #a = 2000;
SET #b = "XYZ";
EXECUTE QUERY USING #a, #b;
DEALLOCATE PREPARE QUERY;
END$$
DELIMITER ;
I want to create a function that will create a unique random id. The parameters will simply be min (the minimum number), max (the maximum number), and tablename (the name of the table to check to see if the id produced by the rand() function already exists).
I have discovered through other posts that you can't pass table names into functions, because functions can't execute dynamic SQL, but you can pass them into stored procedures. I have found numerous examples on StackOverflow of how to pass table names into stored procedures, and they all boil down to using prepared statements.
I have created a stored procedure as shown below:
DELIMITER $$
CREATE DEFINER=`user`#`localhost` PROCEDURE `rand_id`(IN `min` INT, IN `max` INT, IN `tablename` VARCHAR(20) CHARSET utf8, OUT `uid` INT)
BEGIN
DECLARE count_id int;
SET count_id = 1;
SET #s = CONCAT('COUNT(`id`) INTO count_id FROM `', tablename, '` WHERE `id` = ', uid);
WHILE count_id > 0 DO
SET uid = FLOOR(rand() * max + min);
PREPARE stmt from #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
END$$
DELIMITER ;
Whenever I run the following code:
CALL rand_id(1000000000, 9999999999, 'test', #id);
SELECT #id;
I get this 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 'NULL' at line 1
I'm at a loss for what's wrong. I saw somewhere that you can't use user variables inside a stored procedure, but that seems to be incorrect because there are a lot of examples on StackOverflow where the correct solutions do just that.
Sorry for my low level of MySQL understanding. I'm sure my code is fraught with syntax errors and poor design. I appreciate any help I can get. I researched this for quite a while and tried many things but to no avail. The above portion of code is the closest I've been able to get, and yields the least errors, but it's still not working.
Thank you.
EDIT: As per the second example in #Barmar's answer, I changed my code to look like this:
BEGIN
DECLARE count_id int;
SET count_id = 1;
SET #s = CONCAT('SELECT COUNT(`id`) INTO count_id FROM `', tablename, '` WHERE `id` = ?');
PREPARE stmt from #s;
WHILE count_id > 0 DO
SET #uid = FLOOR(rand() * max + min);
EXECUTE stmt USING #uid;
END WHILE;
DEALLOCATE PREPARE stmt;
SET uid = #uid;
END
It seems to have fixed my initial problem but now I get this error:
#1327 - Undeclared variable: count_id
EDIT: Here is my code changed to fit #slaakso's answer, and add in what #Barmar said about using #count_id:
DELIMITER $$
CREATE DEFINER=`mjrinker`#`localhost` PROCEDURE `rand_id`(IN `min` BIGINT, IN `max` BIGINT, IN `tablename` VARCHAR(128) CHARSET utf8, OUT `uid` BIGINT)
BEGIN
SET #count_id = 1;
SET uid = 0;
SET #s = CONCAT('SELECT COUNT(`id`) INTO #count_id FROM `', tablename, '` WHERE `id` = ?');
PREPARE stmt from #s;
WHILE #count_id > 0 DO
SET #uid = FLOOR(rand() * max + min);
EXECUTE stmt USING #uid;
END WHILE;
DEALLOCATE PREPARE stmt;
SET uid = #uid;
END$$
DELIMITER ;
You need to assign #s after you assign the uid variable.
You're also missing the SELECT keyword in your query.
SET #count_id = 1
WHILE #count_id > 0 DO
SET uid = FLOOR(rand() * max + min);
SET #s = CONCAT('SELECT COUNT(`id`) INTO #count_id FROM `', tablename, '` WHERE `id` = ', uid);
PREPARE stmt from #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END WHILE;
But you should actually just prepare the statement once, using a placeholder, which you fill in when using EXECUTE.
SET #count_id = 1
SET #s = CONCAT('SELECT COUNT(`id`) INTO #count_id FROM `', tablename, '` WHERE `id` = ?');
PREPARE stmt from #s;
WHILE #count_id > 0 DO
SET #uid = FLOOR(rand() * max + min);
EXECUTE stmt USING #uid;
END WHILE;
DEALLOCATE PREPARE stmt;
SET uid = #uid;
Note that the parameters to EXECUTE have to be user variables, that's why I changed uid to #uid there. Then we set the output parameter at the end of the loop.
You also need to use a user variable for INTO #count_id.
First of all it is highly unusual to use random numbers as ID's for tables. Mabye you should consider using AUTO_INCREMENT columns.
If you really want to use random numbers, couple of fixes for the code:
You should use value for uid for the first time you run the query
(without it it will be NULL, therefore the error).
You are missing SELECT in your dynamic query
The "INTO count_id" syntax will not work as count_id is not visible inside the dynamic SQL (use #var variable instead)
Your min and max values are declared as INT's, but your passed parameters exceed the INT range (-2147483648 - 2147483647)
i am testing this stored procedure thing and i tried using variables,
BEGIN
DECLARE #day int;
SET #day = 1;
IF (1 = 1) THEN
SET #query = 'SELECT #day';
END IF;
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
this works perfectly fine with a different query and without declaring a variable,i know there is something wrong with the variables and i have researched a lot about this and i cant find any answers. i have this error
If you are on SQL-Server, you must declare the variable: #query.
Just got it.
I just need to do SET #day := 1; instead of SET #day = 1;
1)Below is the code I'm trying for a procedure where I need to compare the count from two different tables. (tbl1 and tbl2 are in parameters to be passed).
But in the above code the values for 'a' and 'b' are set as statements. I need the resultant value(count) from the two statements to compare in the 'IF' condition.
declare a integer;
declare b integer;
set #a:=concat('select count(*) from ', tbl1);
/*PREPARE stmt1 FROM #a;
execute stmt1;
deallocate PREPARE stmt1;*/
set #b:= concat('select count(*) from ', tbl2);
/*PREPARE stmt2 FROM #b;
execute stmt2;
deallocate PREPARE stmt2;*/
if
#a=#b
then
select 1;
else
select 2;
end if;
2) Actually where I am facing a problem to set 'tbl1' and 'tbl2' as parameters in procedure.
The below code works fine if the table names are given directly, but i need them as parameters.
CREATE PROCEDURE myproc (in tbl1 varchar(50), in tbl2 varchar(50))
declare a integer;
declare b integer;
set #a:=(select count(*) from tbl1);
/*PREPARE stmt1 FROM #a;
execute stmt1;
deallocate PREPARE stmt1;*/
set #b:= (select count(*) from tbl2);
/*PREPARE stmt2 FROM #b;
execute stmt2;
deallocate PREPARE stmt2;*/
if
#a=#b
then
select 1;
else
select 2;
end if;
Hope anyone out there can help me with the solution.
As mentioned in the comments above, it is likely that you shouldn't be doing this at all... but, for what it's worth:
SET #sql := CONCAT('SELECT (
SELECT COUNT(*) FROM `',REPLACE('`','``',tbl1),'`
) = (
SELECT COUNT(*) FROM `',REPLACE('`','``',tbl2),'`
);');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql := NULL;
REPLACE() has been used to try and avoid SQL injection (it's somewhat crude, but it's the best one can do without further information).
The below SP is not giving any result even though there are 48 rows as per the where clause
BEGIN
DECLARE SelectClause VARCHAR(2000);
if v_mode='SearchByString' then
SET SelectClause ='select SURVEY_USER.username,SURVEY.* from SURVEY, SURVEY_USER';
if v_SearchString is not null then
SET SelectClause=CONCAT(#SelectClause,' where ');
Set SelectClause=CONCAT(#SelectClause,v_SearchString);
end if;
SET SelectClause=CONCAT(#SelectClause,' order by SURVEY.created_date DESC;') ;
select SelectClause;
SET #query = SelectClause;
PREPARE stmt FROM #query;
EXECUTE stmt;
select stmt;
end if;
END
I tried a lot but not getting any problem. I also tried select clause to print the command at various places to not able to print it.
Please give me some solution.
There are my parameters that I am passing
v_mode='SearhByString'
v_SearchString='SURVEY_USER.username=chiragfanse'
It should return 48 rows but does not return anything.
BEGIN
DECLARE SelectClause VARCHAR(2000);
IF v_mode = 'SearchString' THEN
SET SelectClause = CONCAT('select SURVEY_USER.username,SURVEY.* from SURVEY, SURVEY_USER');
IF SearchString IS NOT NULL THEN
SET SelectClause = CONCAT(SelectClause, ' where ', SearchString);
END IF;
SET SelectClause = CONCAT(SelectClause, ' order by SURVEY.created_date DESC;');
SET #query = SelectClause;
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END
All declaration have to be at the begining.
Rename #SelectClause to SelectClause, because you are declaring this variable.
Check the usage of SET clauses. I have added one.
Have a look at prepared statements reference, it will help you to execute the query you built.
you have wrong concat functions. Try this.
if v_mode='SearchString' then
DECLARE #SelectClause varchar(2000);
SET #SelectClause =CONCAT(select (SURVEY_USER.username,SURVEY.*) from SURVEY, 'SURVEY_USER');
if SearchString is not null then
#SelectClause=CONCAT(#SelectClause, 'where' ,SearchString);
end if;
SET #SelectClause=#SelectClause
order by SURVEY.created_date DESC
execute(#SelectClause)
end if;
try this. let me know if you need anything else.