MySQL Global userdefined variable in procedure - mysql

I want to store the output from a PROCEDURE into a global userdefined VAR so i can use this "list" in an other PROCEDURE on a different database.
Second, if the VAR is used on the 2nd PROCEDURE it should be unset, because on next CALL it will append or?
Thanks for response!
BEGIN
SELECT `steamid` FROM `mybb_users` WHERE `steamid`!='';
END
The SELECT shout go into a global variable, so i can use the result in another procedure...

As far as I know, you can't return a row set as a result of a procedure in MySQL.
I would solve it by creating a temporary table in the first procedure, and then use that temp table in the second procedure. Something like this:
delimiter $$
create procedure procedure1()
begin
drop table if exists temp_table;
create temporary table temp_table
select steamid from mybb_users where steamid != '';
-- add the appropriate indexes here
-- alter table temp_table
-- add index ...
end $$
create procedure procedure2()
begin
-- Do whatever you want to do with temp_table
end $$
delimiter ;
Remember:
A temporary table is visible only to the connection that created it.
If the connection is closed, the temporary table will be deleted.
Temporary tables are created directly to RAM (if they are not very big), so they can be pretty fast to read.
Each connection can create temporary tables with the same name, as each connection will have a "copy" of that temp table.

Related

Create Trigger inside stored procedure in mysql

I want to create an trigger inside an procedure. but after some research I got to know that it is not possible. can u suggest me another way I can achieve the below actions. (I cant share exact data and queries due to some reason. please refer similar queries.)
What I want
I have created an temporary table containing data i need.
eg. CREATE TEMPORARY TABLE temp1 SELECT id, col_1 FROM table1 WHERE col_1=2;
I want to inset data in table table2 when data is inserted in temp1, which i can achieve by creating a TRIGGER. but the problem is I want to give a value in table2 which will be dynamic and will be taken from nodejs backend. so i created a PROCEDURE which takes parameter neededId. but i cant created trigger inside a procedure. is their any other way i can achieve this?
Procedure I Created
here neededId is the foreign key I get from backend to insert
DELIMITER $$
USE `DB`$$
CREATE PROCEDURE `MyProcedure` (IN neededID int)
BEGIN
DROP TABLE IF EXISTS temp1;
CREATE TEMPORARY TABLE temp1 SELECT id, col_1 FROM table1 WHERE col_1=2;
DROP TRIGGER IF EXISTS myTrigger;
CREATE TRIGGER myTrigger AFTER INSERT ON temp1 FOR EACH ROW
BEGIN
INSERT into table2("value1", "value2", neededId);
END;
END$$
DELIMITER ;
SQL Statements Not Permitted in Stored Routines
Generally, statements not permitted in SQL prepared statements are also not permitted in stored programs. ... Exceptions are SIGNAL, RESIGNAL, and GET DIAGNOSTICS, which are not permissible as prepared statements but are permitted in stored programs.
SQL Syntax Permitted in Prepared Statements
CREATE TRIGGER is not listed.
Finally: the trigger cannot be created in stored procedure, function, prepared statement, trigger or event procedure.
In MySQL, you can't create a trigger for a temporary table, regardless of whether you do it in a stored procedure or not.
https://dev.mysql.com/doc/refman/8.0/en/create-trigger.html says:
The trigger becomes associated with the table named tbl_name, which must refer to a permanent table. You cannot associate a trigger with a TEMPORARY table or a view.
I assume the same is true of MariaDB. It's not clear from your question which one you use. You say MySQL at first, but you tagged the question mariadb. Be aware that these are not the same database product, and they are not necessarily compatible.
Here's a demo of the error, tested on MySQL 8.0.28:
mysql> create temporary table t ( i int );
mysql> create trigger t before insert on t for each row set NEW.i = 42;
ERROR 1361 (HY000): Trigger's 't' is view or temporary table
So in your case, you cannot use a trigger for the temporary table. You'll have to think of a different way to implement inserts to your second table.

MySQL Temp table Insert

I'm using MySQL and trying to create a temp table. I will be doing a 2 while loop statements in PHP to populate the temp table. Firstly though I can't seem to get the Insert into temp table to work. I've tried many different versions of this, some using '#' for the table and various things (are there differences in SQL server and MySQL commands?). Here's my last attempt (P.S the Select statement works fine on its own).
CREATE TEMPORARY TABLE temp
(
aID varchar(15) NOT NULL,
bID varchar(15) NOT NULL
)
INSERT INTO temp
SELECT aID, bID
FROM tags
WHERE placeID = "abc" AND tagID = "def";
Help appreciated!
Also, just a general Q...this query will have to be run many times. Will using temp tables be OK or cause the server issues?
working on what Code-Monk wrote, consider the following:
drop procedure if exists uspK;
DELIMITER $$
create procedure uspK ()
BEGIN
drop temporary table if exists temp; -- could be some other random structure residue
create temporary table temp
SELECT aID, bID
FROM tags
WHERE placeID = "abc" AND tagID = "def";
-- use the temp table somehow
-- ...
-- ...
-- ...
drop temporary table temp; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
Test Stored Procedure
call uspK(); -- test it, no warnings on edge conditions
What not to do
One would not find much luck with the following. If you think so, run it a few times;
drop procedure if exists uspK;
DELIMITER $$
create procedure uspK ()
BEGIN
-- drop temporary table if exists temp;
create temporary table if not exists temp
SELECT aID, bID
FROM tags
WHERE placeID = "abc" AND tagID = "def";
-- use the temp table somehow
-- ...
-- ...
-- ...
-- drop temporary table temp; -- otherwise it survives the stored proc call
END
$$ -- signify end of block
DELIMITER ; -- reset to default delimiter
because create temporary table if not exists temp is flakey
General Comments
One should not embark into writing stored procs until somewhat fluent on the simple topic of DELIMITERS. Wrote about them in a section here called Delimiters. Just hoping to head you off from unnecessary wasted time on such a simple thing, than can waste a lot of debugging time.
Also, here in your question, as well as in that reference, keep in mind that the creation of tables is DDL that can have a large percentage of the overall profiling (performance). It slows down a proc versus using a pre-existing table. One might think the call is instantaneous, but it is not. As such, for performance, using a pre-existing table with ones results put into their own segmented rowId is much faster than enduring DDL overhead.
You can create temporary table and insert select statemet in following way:
create temporary table temp
SELECT aID, bID
FROM tags
WHERE placeID = "abc" AND tagID = "def";
To drop the temporary table before creating it again. put following statement before creating temporary table:
drop temporary table if exists temp;
Note: It will be good if you can put all this code in stored procedure. and call it to create temporary table.

In memory table and temp table in MySql

I am looking for Sql-Server relevant feature in MySql
Table variable inside procedure. here
Temporary Table inside procedure. here
I hope the table variables are in-memory and temporary tables are stored in temp database.
If both declared inside procedure, both will be cleaned after the procedure finished its execution.
MySql provides only one option called Temporary Table. How to achieve these two? and do we need to clear those tables or MySql will take care of it after the procedure completed?
From MySQL documentation:
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only to the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name.
More info: http://dev.mysql.com/doc/refman/5.1/en/create-table.html#create-temporary-table
But what happens if I'm using a single connection? May be you will have some data conflicts. In the past I use temporary tables with a unique id to avoid conflicts if I call the procedure with the same connection more than one time:
DELIMITER $$
DROP PROCEDURE some_proc $$
CREATE PROCEDURE some_proc ()
BEGIN
-- creating a unique value
DECLARE VARIABLE tmp_uuid varchar(50);
SET tmp_uuid = uuid();
CREATE TEMPORARY TABLE IF NOT EXISTS tbl_temporary
(
uuid_id varchar(50),
col1 varchar(10),
col2 varchar(10),
INDEX(uuid_id)
);
-- do some operations on that
INSERT INTO tbl_temporary(uuid_id, ...) VALUES (tmp_uuid,...);
-- now, cleaning the data
DELETE FROM tbl_temporary WHERE uuid_id = tmp_uuid;
-- if the current session is closed the table will be automatically deleted
END$$
DELIMITER ;

Creating temporary tables in MySQL Stored Procedure

The following procedure gives me an error when I invoke it using the CALL statement:
CREATE DEFINER=`user`#`localhost` PROCEDURE `emp_performance`(id VARCHAR(10))
BEGIN
DROP TEMPORARY TABLE IF EXISTS performance;
CREATE TEMPORARY TABLE performance AS
SELECT time_in, time_out, day FROM attendance WHERE employee_id = id;
END
The error says "Unknown table 'performance' ".
This is my first time actually using stored procedures and I got my sources from Google. I just cant figure out what I am doing wrong.
I've tidied it up a little for you and added example code. I always keep my parameter names the same as the fields they represent but prefix with p_ which prevents issues. I do the same with variables declared in the sproc body but prefix with v_.
You can find another one of my examples here:
Generating Depth based tree from Hierarchical Data in MySQL (no CTEs)
drop procedure if exists emp_performance;
delimiter #
create procedure emp_performance
(
in p_employee_id varchar(10)
)
begin
declare v_counter int unsigned default 0;
create temporary table tmp engine=memory select time_in, time_out
from attendance where employee_id = p_employee_id;
-- do stuff with tmp...
select count(*) into v_counter from tmp;
-- output and cleanup
select * from tmp order by time_in;
drop temporary table if exists tmp;
end#
delimiter ;
call emp_performance('E123456789');
By default MySQL config variable sql_notes is set to 1.
That means that
DROP TEMPORARY TABLE IF EXISTS performance;
increments warning_count by one and you get a warning when a stored procedure finishes.
You can set sql_notes variable to 0 in my.cnf or rewrite stored procedure like that:
CREATE DEFINER=`user`#`localhost` PROCEDURE `emp_performance`(id VARCHAR(10))
BEGIN
SET ##session.sql_notes = 0;
DROP TEMPORARY TABLE IF EXISTS performance;
CREATE TEMPORARY TABLE performance AS
SELECT time_in, time_out, day FROM attendance WHERE employee_id = id;
SET ##session.sql_notes = 1;
END

How to use DROP TABLE IF EXISTS in a MySQL Stored Procedure

I want to know how to use DROP TABLE IF EXISTS in a MySQLstored procedure.
I'm writing a rather long mySQL Stored Procedure that will do a bunch of work and then load up a temp table with the results. However, I am having trouble making this work.
I've seen a few ways to do the temp table thing. Basically, you either create the temp table, work on it, and then drop it at the end ... or you drop it if it exists, create it, and then do your work on it.
I prefer the second method so that you always start of clean, and it's a built-in check for the table's existence. However, I can't seem to get it to work:
Here are my examples:
This Works:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
DROP TEMPORARY TABLE tblTest;
END//
DELIMITER ;
CALL pTest();
This Works:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
CALL pTest();
This does not:
DELIMITER//
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
CALL pTest();
The first 2 work, but if that table exists (like if the procedure didn't finish or something), it'll obviously end with a "Table tblTest does not exist" error. The non-working example is what I'm looking for -- drop the table if its there and then recreate it so that I can start clean.
It feels like it's the "IF EXISTS" making this thing fail. I've copied code from all sorts of sites that do things very similar and in no case can I get a "DROP TABLE IF EXISTS..." to work. Ever.
Dev Server: mySQL Server version: 5.1.47-community
Prod Server: mySQL Server version: 5.0.45-log
We can't change db versions (DBAs won't allow it), so I'm stuck on what I have. Is this a bug in mySQL or in the Procedure?
Thanks.
It's an old question but it came up as I was looking for DROP TABLE IF EXISTS.
Your non-working code did not work on my MySQL 5.1.70 server.
All I had to do was add a space between DELIMITER and // on the first line, and everything worked fine.
Working code:
DELIMITER //
DROP PROCEDURE IF EXISTS pTest//
CREATE PROCEDURE pTest()
BEGIN
DROP TEMPORARY TABLE IF EXISTS tblTest;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END//
DELIMITER ;
I don't know why this is not working for you,but you should be able to work around the issue using a continue handler. If you put the DROP TABLE statement into it's own BEGIN...END block you can use a continue handler to ignore the error if the table does not exist.
Try this:
DELIMITER //
DROP PROCEDURE IF EXISTS pTest //
CREATE PROCEDURE pTest()
BEGIN
BEGIN
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' BEGIN END;
DROP TEMPORARY TABLE tblTest;
END;
CREATE TEMPORARY TABLE tblTest (
OrderDate varchar(200)
);
END //
DELIMITER ;
CALL pTest();
I also had the same problem. It seems MySQL doesn't like to check if the table exists on some versions or something. I worked around the issue by querying the database first, and if I found a table I dropped it. Using PHP:
$q = #mysql_query("SELECT * FROM `$name`");
if ($q){
$q = mysql_query("DROP TABLE `$name`");
if(!$q) die('e: Could not drop the table '.mysql_error());
}
You suppress the error in the first query with the # symbol, so you don't have an interfering error, and then drop the table when the query returns false.
I recommend to add new line
SET sql_notes = 0// before DROP PROCEDURE IF EXISTS get_table //
Otherwise it will show warning PROCEDURE does not exists.