That I need is
Save all of query in one table
query_id | sql_query
1 | select * from ms_user
2 | select * from ms_privileges
Create Procedure
this procedure will call
call my_procedure(query_id)
I tried the code below
DROP PROCEDURE IF EXISTS mp_test;
CREATE PROCEDURE global_procedire(IN id_query int(10));
BEGIN
SET #Query = 'SELECT sql_query from ms_query where query_id = id_query';
SET #Query = CONCAT(#Query);
PREPARE stmt FROM #Query;
EXECUTE stmt;
END
Related
I'm creating a MySQL stored procedure that receives the names of two views, and performs a Union upon them into the first of the two.
I've used prepared statements to take view names as strings, so I can use this stored procedure with a wealth of other stored procedures that produce views of varying names.
The following code works as expected:
DROP view if exists test1;
DROP view if exists test2;
CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";
DROP VIEW if exists tempView;
CREATE VIEW tempView AS SELECT * FROM test1 UNION SELECT * FROM test2;
SELECT * from tempView;
However, when I execute the following code:
DELIMITER //
DROP PROCEDURE IF EXISTS SP_unionViews //
CREATE PROCEDURE SP_unionViews(IN viewname varchar(255),
IN viewname2 varchar(255))
BEGIN
DROP VIEW IF EXISTS tempView;
SET #in1 = viewname;
SET #in2 = viewname2;
SET #str = 'CREATE VIEW tempView AS
SELECT * FROM ? UNION SELECT * FROM ?';
PREPARE stmt FROM #str;
EXECUTE stmt USING #in1, #in2;
SET #str2 = 'DROP VIEW ?';
SET #in3 = viewname;
PREPARE stmt2 FROM #str2;
EXECUTE stmt2 USING #in3;
SET #str3 = 'CREATE VIEW ? AS SELECT * FROM tempView';
PREPARE stmt3 FROM #str3;
EXECUTE stmt3 USING #in3;
DEALLOCATE PREPARE stmt;
DEALLOCATE PREPARE stmt2;
DEALLOCATE PREPARE stmt3;
END //
DELIMITER ;
DROP view if exists test1;
DROP view if exists test2;
CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";
CALL SP_unionViews(test1, test2);
SELECT * from test1;
I get the following error:
#1054 - Unknown column 'test1' in 'field list'
That would seem to indicate that this stored procedure is trying to use test1 as a column somewhere it's not intended to be one. But I can't figure out where.
UPDATE:
When edited as below, I expected the solution to work, but it gives me another error.
The new code reads:
DELIMITER //
DROP PROCEDURE IF EXISTS SP_unionViews //
CREATE PROCEDURE SP_unionViews(IN viewname varchar(255),
IN viewname2 varchar(255))
BEGIN
DROP VIEW IF EXISTS tempView;
SET #str = CONCAT('
CREATE VIEW tempView AS
SELECT * FROM ', viewname, ' UNION SELECT * FROM ', viewname2);
PREPARE stmt FROM #str;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #str2 = CONCAT('DROP VIEW ', viewname, ';');
PREPARE stmt2 FROM #str2;
EXECUTE stmt2;
DEALLOCATE PREPARE stmt2;
SET #str3 = CONCAT('CREATE VIEW ', viewname ,' AS SELECT * FROM tempView');
PREPARE stmt3 FROM #str3;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END //
DELIMITER ;
DROP view if exists test1;
DROP view if exists test2;
CREATE VIEW test1 as SELECT "Cows";
CREATE VIEW test2 as SELECT "Horses";
CALL SP_unionViews("test1", "test2");
SELECT * from test1;
And its error reads:
#1615 - Prepared statement needs to be re-prepared
You can't use parameters for table names in a prepared statement, so you will need to put the table names into the query string before you prepare the statement. Try changing your queries to these:
SET #str = CONCAT('
CREATE VIEW tempView AS
SELECT * FROM (
SELECT * FROM ', viewname, ' UNION SELECT * FROM ', viewname2, '
)');
SET #str2 = CONCAT('DROP VIEW ', viewname);
SET #str3 = CONCAT('CREATE VIEW ', viewname, ' AS SELECT * FROM tempView');
Once you have done this you will no longer need any parameters to the EXECUTEs
I need some help about executing expression(bitwise) stored in a column of a table.
Input :
ID | expression
----|-------------
1 | 1&0
2 | (1&1)|(0&1)
Desired Output :
ID | expression | value
----|-------------|-------
1 | 1&0 | 0
2 | (1&1)|(0&1) | 1
I am trying something like below but it is not executing the expression.
PREPARE stmt from 'select ? into #outvar';
set #invar = '1&0';
execute stmt using #invar;
select #outvar;
The output of above is 1&0 but the desired output is 0.
Actually I want to store the output in a variable as framed in my above pseudo code.
I have built you a procedure to do this
DROP TABLE IF EXISTS test10;
DROP PROCEDURE IF EXISTS `sp_test10`;
create table test10 (ID int, expression VARCHAR(20));
insert into test10 values ( 1 , '1&0');
insert into test10 values ( 2 , '(1&1)|(0&1)');
CREATE PROCEDURE sp_test10 (IN IN_ID int, OUT OUT_VAL INT)
BEGIN
SELECT expression INTO #exp FROM test10 WHERE ID=IN_ID;
SET #q = CONCAT('SELECT ',#exp,' INTO #exp ');
PREPARE stmt1 FROM #q;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
SET OUT_VAL = #exp;
END\\
;
call sp_test10(2,#result);
select #result;
Results :
call sp_test10(1,#result) returns 0
call sp_test10(2,#result) returns 1
http://rextester.com/live/SMLB31207
Using prepared statements, what are sent to server in the second round are treated literally. They can't be part of SQL. You shouldn't use placeholders for this:
SET #invar = '(1&1)&(0&1)';
SET #s = CONCAT('SELECT ', #invar, ' INTO #outvar');
PREPARE stmt FROM #s;
EXECUTE stmt;
SELECT #outvar;
I have the following stored procedure . I'm trying to insert the users from the table usuaris, whose admin variable is equal to 1, into the table that the stored procedure creates with the name( nombre varchar(50)) that is passed as a parameter.
When the procedure is called, it duplicates the user 'mary' with id 4. I've tried a couple of ways to implement the logic condition in order to avoid the duplication, but still, I'm missing something and I can't get the desired result. In the code below, the logic condition before the insertion is the last thing I've tried. Any ideas?
Thanks.
CREATE DEFINER=`root`#`localhost` PROCEDURE `createNewtable`(nombre varchar(50))
BEGIN
/*variable declaration*/
declare centinela int ;
declare id1 int ;
declare nom1 varchar(50);
declare admin1 enum('0','1') ;
declare cadena varchar(100); /*string to concatenate table creation and insertion*/
/*cursor declaration*/
declare cursor1 cursor for select * from users.usuaris where admin = '1' ;
declare continue handler for not found set #centinela = 1 ;
/*create the table with the name that's passed as parameter*/
set #cadena=concat("create table ",nombre,
"(
id2 int not null primary key,
nom2 varchar(50),
admin2 enum ('0','1')
)" );
prepare stmt from #cadena ;
execute stmt ;
deallocate prepare stmt;
/* loop that fetches the data from the table usuaris and
inserts them into the newly created table. */
set #centinela = 0 ;
open cursor1 ;
bucle: loop
fetch cursor1 into id1,nom1,admin1 ;
if ( centinela = 1 ) then
leave bucle ;
end if ;
/*logic condition to avoid entry duplication */
if not exists (select * from users.usuaris where admin='1' and id=#id1) then
set #cadena=concat("insert into ",nombre," values( ",id1,",'",nom1,"','",admin1,"')");
end if;
select #cadena;
prepare stmt from #cadena;
execute stmt ;
deallocate prepare stmt;
end loop bucle;
close cursor1;
END
Here is the single-table database of users :
create database if not exists `users` ;
use `users` ;
create table usuaris(
id int not null auto_increment primary key ,
nom varchar(50),
admin enum ('0','1')
);
insert into usuaris(id,nom,admin)
values
(1,'jose','1'),
(2,'maria','0'),
(3,'frank','1'),
(4,'mary','1'),
(5,'godfrey','0') ;
Also it has to duplicate jose. The reason of duplication - if the IF statement isn't TRUE then you don't set the new #cadena variable BUT anyway execute PREVIOUS #cadena statement. You should move execution into the IF statement also:
if not exists (select * from users.usuaris where admin='1' and id=#id1) then
set #cadena=concat("insert into ",nombre," values( ",id1,",'",nom1,"','",admin1,"')");
select #cadena;
prepare stmt from #cadena;
execute stmt ;
deallocate prepare stmt;
end if;
Also in SQL you should always try to avoid loops if it possible and use SQL statements instead.
You can replace your loop with one SQL statement:
INSERET INTO NEW_TABLE_NAME_HERE
SELECT id1,nom1,admin1
FROM users.usuaris where admin<>'1'
Further more you can use SELECT INTO statement syntax to automatically create new table without CREATE TABLE statement:
SELECT id1 as id2,
nom1 as nom2,
admin1 as admin2
INTO NEW_TABLE_NAME_HERE
FROM users.usuaris where admin<>'1'
Change ur below code to my new code and try-
Existing Code
if not exists (select * from users.usuaris where admin='1' and id=#id1) then
set #cadena=concat("insert into ",nombre," values( ",id1,",'",nom1,"','",admin1,"')");
end if;
select #cadena;
prepare stmt from #cadena;
execute stmt ;
deallocate prepare stmt;
New Code-
SET #cnt=SELECT count(*) FROM users.usuaris WHERE admin='1' AND id=#id1
IF #cnt>0 THEN
SET #cadena=CONCAT("insert into ",nombre," values( ",id1,",'",nom1,"','",admin1,"')");
prepare stmt from #cadena;
execute stmt ;
deallocate prepare stmt;
end if;
I'm trying the following but I'm getting the following error:
ERROR 1054 (42S22): Unknown column 'f' in 'where clause'
I'm seriously confused because f is a parameter of createtableTest...
CREATE PROCEDURE createtableTest
(
tname2 varchar(20),
f varchar(20)
)
BEGIN
DROP TABLE IF EXISTS tname2;
CREATE TABLE tname2 as SELECT * FROM data WHERE group_name like f;
END;
Since f is contains the value, a dynamic sql is needed so we can concatenate it with the original query,
DELIMITER $$
CREATE PROCEDURE createtableTest(IN tname2 varchar(20),IN f varchar(20))
BEGIN
DROP TABLE IF EXISTS tname2;
SET #sql = CONCAT('CREATE TABLE tname2 as SELECT * FROM data WHERE group_name like ''%',f,'%''');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
for example, the value of f is hello, the concatenated string will produce
CREATE TABLE tname2 as SELECT * FROM data WHERE group_name like '%hello%'
UPDATE
MySQL Prepared Statements
Aside from concatenation, you can also parameterized the value which is the best way, ex
DELIMITER $$
CREATE PROCEDURE createtableTest(IN tname2 varchar(20),IN f varchar(20))
BEGIN
DROP TABLE IF EXISTS tname2;
SET #sql = CONCAT('CREATE TABLE tname2 as SELECT * FROM data WHERE group_name like ?');
PREPARE stmt FROM #sql;
SET #val = CONCAT('%', f, '%');
EXECUTE stmt USING #val;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
I am stuck in Mysql today with the dynamic column name need in mysql select statement. Let me explain:
sql> select name1 from namescollection.
sql> select name2 from namescollection.
sql> select name3 from namescollection.
So namescollection table has three columns having name1, name2, name3
I would like to query this table in my stored procedure being 1,2,3 as dynamic and would be passed as a variable, but on the simple sql too when i query:
SELECT concat('name','1') FROM `namescollection`
name1 ----- name1 rather fetching name1 field's value.
Can any suggest on this, the right function i need to use rather concat though I know its right to output name1 when I am calling concat but I want to use it as column name.
What you can do is use a prepared statement within your stored procedure which will allow you to execute a string query:
As a simple example:
DELIMITER //
CREATE PROCEDURE selname (IN col VARCHAR(20))
BEGIN
SET #sql = CONCAT('SELECT ', col, ' FROM tbl');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END//
DELIMITER ;
Test it out with this SQLFiddle Demo
Dynamic column name in store procedure Update statement :
DELIMITER //
CREATE DEFINER=`root`#`localhost` PROCEDURE `selname`()
BEGIN
declare cl int ;
declare clvalue int ;
set cl=1;
SET clvalue=1;
while cl < 4 DO
SET clvalue=clvalue*cl;
SET #sql = CONCAT('update test set col',cl, '=',clvalue,' where id=1');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set cl=cl+1;
end while;
END //
DELIMITER ;