Create Trigger inside stored procedure in mysql - 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.

Related

MySQL REPLACE Table Values using Identical Staging table Trigger Without Defining Columns

Within a MySQL 8 database I have two identical tables in different schemas with one being used as a staging table for its equivalent production table. The tables contain 200+ columns with more to be added in the future, making explicitly defining values for column names difficult.
I need to INSERT or UPDATE values in the production table with those in the staging table using an AFTER INSERT trigger, where all values of a row within the production table are replaced upon the existence of a duplicate PRIMARY KEY. Note that the production table has its PRIMARY KEY defined.
After this, I should delete all rows from the staging table.
Here is the code I have tried:
CREATE TRIGGER stage.my_table_after_insert AFTER INSERT ON my_table
FOR EACH ROW
BEGIN
REPLACE INTO prod.my_table
SELECT * FROM new;
DELETE FROM stage.my_table
END
I don't get why are You doing so, but why arent you doing something like:
REPLACE INTO prod.my_table
SELECT * FROM stage.my_table;
DELETE FROM stage.my_table;
You cant alter a table within its own contained trigger. Additionally, using a trigger will execute all SQL statements once per row (inefficient in this case). Therefore, a procedure is instead used to perform the required functions, using the following:
DELIMITER $$
CREATE PROCEDURE stage.load_data()
BEGIN
REPLACE INTO prod.my_table
SELECT * FROM stage.my_table;
DELETE FROM stage.my_table;
END$$
DELIMITER ;

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 ;

MySQL Global userdefined variable in procedure

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.

Stored Procedure with a IN statement (mysql)

I have a query like
Select id,name,... FROM table WHERE id IN (?)
The query is actually more complicated with joins and another (?) with the same ids. I've been told to put it on a stored procedure to make it easier to manage and safer, but mysql doesn't support arrays, so I'm not sure what is the best way to do it, considering that I don't know how many id I will have to pass. I have seen people passing a string. Is it the only way?
You can use temporary tables. Though this answer is not highly voted so I suppose that using a string parameter is the prefered way (17 votes vs 2 votes) (see the link). The answer with temporary table is taken from another question: Pass array to MySQL stored routine
Use a join with a temporary table. You don't need to pass temporary
tables to functions, they are global.
create temporary table ids( id int ) ;
insert into ids values (1),(2),(3) ;
delimiter //
drop procedure if exists tsel //
create procedure tsel() -- uses temporary table named ids. no params
READS SQL DATA
BEGIN
-- use the temporary table `ids` in the SELECT statement or
-- whatever query you have
select * from Users INNER JOIN ids on userId=ids.id ;
END //
DELIMITER ;
CALL tsel() ; -- call the procedure

Mysql triggers Create error

This is my create triggers . I want when Insert vhftofass it execute this query(UPDATE vhf_msg_rx SET msg_text="";) that means Its make Null this table vhf_msg_rx.But when i write that query after insert Query it make error (Can't update table 'vhf_msg_rx' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.) Please help me how can i do this
CREATE
/*!50017 DEFINER = 'root'#'localhost' */
TRIGGER `VHFtoFASS` AFTER UPDATE ON `vhf_msg_rx`
FOR EACH ROW BEGIN
INSERT INTO vhftofass SELECT NULL,msg_text,NOW(),0 FROM vhf_msg_rx WHERE msg_text<>"";
END;
$$
I'm not completely clear on what you're trying to do, but it seems like you want to copy modified rows of one table into another, but only retaining certain fields. You could do that by referencing the inserted record with NEW.columnname inside the FOR EACH ROW loop, for example
CREATE TRIGGER `VHFtoFASS` AFTER UPDATE ON `vhf_msg_rx`
FOR EACH ROW BEGIN
INSERT INTO vhftofass VALUES(NULL,NEW.msg_text,NOW(), 0);
END;
Note that this will only handle updates - you'll need an INSERT trigger to capture new rows.