Use trigger with code operating on two databases - mysql

How can I use a trigger that accesses two databases?
This is what I tried:
CREATE DEFINER=`root`#`localhost` TRIGGER `db1`.`library_AFTER_UPDATE`
AFTER UPDATE ON `library` FOR EACH ROW
begin
insert into `db2`.email(account_code,account_name,admin_first_name,admin_email,last_updated_date,updated_by) values('146','Abcds','SSSSSSSS','jnkjk#gmli',now(),'anupam');
end

Here is a simple example on after Update trigger. I am using 2 databases test and test2. This example can help you-
use test
create table test.foo (a INT, b INT, ts TIMESTAMP);
create table test2.bar (a INT, b INT);
INSERT INTO test.foo (a,b) VALUES(1,1);
INSERT INTO test.foo (a,b) VALUES(2,2);
INSERT INTO test.foo (a,b) VALUES(3,3);
DELIMITER ///
CREATE TRIGGER ins_sum AFTER UPDATE ON foo
FOR EACH ROW
BEGIN
INSERT INTO test2.bar (a, b) VALUES(NEW.a, NEW.b);
END;
///
DELIMITER ;
select * from test.foo;
+------+------+---------------------+
| a | b | ts |
+------+------+---------------------+
| 1 | 1 | 2011-06-14 09:29:46 |
| 2 | 2 | 2011-06-14 09:29:46 |
| 3 | 3 | 2011-06-14 09:29:46 |
+------+------+---------------------+
3 rows in set (0.00 sec)
-- UPDATE without change
UPDATE test.foo SET b = 3 WHERE a = 3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
select * from test2.bar;
+------+------+
| a | b |
+------+------+
| 3 | 3 |
+------+------+
1 row in set (0.00 sec)

Related

Error #1054 in MySQL Trigger

This is my trigger.
DELIMITER //
CREATE TRIGGER verificare_masa
BEFORE INSERT ON Rezervare
FOR EACH ROW
BEGIN
IF (NEW.Data_Rezervarii=Data_Rezervarii) AND (NEW.NumarMasa=NumarMasa) THEN
SET NEW.NumarMasa= NULL;
END IF;
END //
DELIMITER ;
I want to make trigger on 1 table (rezervare).
When I execute the trigger, it has been created. But, when I insert data into table rezervare, It become
Error Code: 1054. Unknown column 'Data_Rezervarii' in 'field list'
I want to check if a reservation is already in the data base for that date
and mass required is already reserved for that date
From your attempt, it appears that you want to still insert a new row with the same Data_Rezervarii, but with NumarMasa NULL. If so, your trigger should be something like
CREATE TRIGGER verificare_masa
BEFORE INSERT ON Rezervare FOR EACH ROW
SET NEW.NumarMasa = IF(EXISTS(
SELECT 1 FROM Rezervare
WHERE Data_Rezervarii=NEW.Data_Rezervarii
AND NumarMasa = NEW.NumarMasa
),NULL,NEW.NumarMasa);
Then it would work like this:
MariaDB [test]> select * from Rezervare;
+-----------------+-----------+
| Data_Rezervarii | NumarMasa |
+-----------------+-----------+
| 2016-12-12 | 1 |
| 2016-12-12 | 2 |
| 2016-12-13 | 3 |
+-----------------+-----------+
3 rows in set (0.00 sec)
MariaDB [test]> INSERT INTO Rezervare VALUES ('2016-12-12',1),('2016-12-12',4);
Query OK, 2 rows affected (0.20 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [test]> select * from Rezervare;
+-----------------+-----------+
| Data_Rezervarii | NumarMasa |
+-----------------+-----------+
| 2016-12-12 | 1 |
| 2016-12-12 | 2 |
| 2016-12-13 | 3 |
| 2016-12-12 | NULL |
| 2016-12-12 | 4 |
+-----------------+-----------+
5 rows in set (0.00 sec)
But if you actually want to skip the new record completely if one already exists in the table, it should be done by adding a unique index on these two columns and using INSERT IGNORE.

MySQL SELECT returns NULL for NOT NULL column in stored procedure

I have a stored procedure in which I'm trying to loop over a number of IDs in a table and insert them into another table... problem is the ID turns out as NULL in the loop.
For debugging purposes I have created a table called test, it has two columns named var_name and value. I also made a stored procedure like this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `myProcedure`(#parent INT(11))
BEGIN
INSERT INTO `test`
(`var_name`, `value`)
VALUES
('parent', #parent);
INSERT INTO test (`var_name`, `value`)
SELECT 'id', `id`
FROM `mytable`
WHERE `parent` = #parent;
END
The table mytable has a lot of columns but id is the primary key and obviously NOT NULL, parent allows NULL. The id, parent and value columns are all INT(11).
The following statement:
CALL myProcedure(1);
Produces the following result in test:
+----------+-------+
| var_name | value |
+----------+-------+
| 'parent' | 1 |
| 'id' | NULL |
| 'id' | NULL |
| 'id' | NULL |
| 'id' | NULL |
| 'id' | NULL |
| 'id' | NULL |
+----------+-------+
The number of 'id' rows match the number of rows in mytable with parent = 1, but value is always NULL. Running the following query:
SELECT `id` FROM `mytable` WHERE `parent` = 1;
Produces the expected result:
+----+
| id |
+----+
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
+----+
What's going on here?
Not quite sure what is wrong with the given procedure but I tried creating one similar to yours and it worked pretty well. Here what I did
mysql> create table test (var_name varchar(100),value int);
Query OK, 0 rows affected (0.10 sec)
mysql> create table mytable (id int, parent int);
Query OK, 0 rows affected (0.07 sec)
mysql> insert into mytable values (2,1),(3,1),(4,1),(5,1),(6,1),(7,1);
Query OK, 6 rows affected (0.02 sec)
Records: 6 Duplicates: 0 Warnings: 0
Then added the following procedure
delimiter //
CREATE PROCEDURE myProcedure(parent INT(11))
BEGIN
declare parent_id int ;
set #parent_id := parent ;
INSERT INTO `test`
(`var_name`, `value`)
VALUES
('parent', #parent_id);
INSERT INTO test (`var_name`, `value`)
SELECT 'id', `id`
FROM `mytable`
WHERE `parent` = #parent_id;
END; //
mysql> CALL myProcedure(1);
Query OK, 6 rows affected (0.05 sec)
mysql> select * from test ;
+----------+-------+
| var_name | value |
+----------+-------+
| parent | 1 |
| id | 2 |
| id | 3 |
| id | 4 |
| id | 5 |
| id | 6 |
| id | 7 |
+----------+-------+
7 rows in set (0.00 sec)
Only thing I changed is used a variable inside the procedure to hold the param value and use it in the query.
I lied a little bit in the question. My real stored procedure contained the portion I posted at the beginning, but after a couple of DECLARE, including:
DECLARE id INT;
which replaced the value of id in mytable...

MYSQL Trigger works if I use 'after update' but not 'after insert'?

I've written a trigger to insert a row into table b after an operation on table a.
For some reason, it has no effect if I add this trigger 'after insert' and then insert a row. However, it does work if I add the trigger as 'after update', and update the row.
Here's the trigger code. When I replace 'AFTER UPDATE' with 'AFTER INSERT', and do an insert, then nothing happens when i insert a new row. I get no errors when creating the trigger, and I am not trying to update the same table the trigger is being set upon.
Any help is appreciated!
thanks,
Jen
drop trigger if exists insertUndecided;
DELIMITER //
CREATE TRIGGER insertUndecided
AFTER UPDATE ON jiraissue
FOR EACH ROW
BEGIN
insert into nodeassociation (SOURCE_NODE_ID, SOURCE_NODE_ENTITY, SINK_NODE_ID, SINK_NODE_ENTITY, ASSOCIATION_TYPE, SEQUENCE)
select
NEW.id as SOURCE_NODE_ID,
'Issue' as SOURCE_NODE_ENTITY,
(select pv.id from projectversion pv
where pv.vname='undecided'
and pv.project=NEW.project ) as SINK_NODE_ID,
'Version' as SINK_NODE_ENTITY,
'IssueFixVersion' as ASSOCIATION_TYPE,
NULL as SEQUENCE
from dual where exists
(select pkey from jiraissue
where id=NEW.id and id not in
(select distinct source_node_id from nodeassociation
where source_node_entity='Issue' and SINK_NODE_ENTITY='Version'
and ASSOCIATION_TYPE='IssueFixVersion') );
END;//
DELIMITER ;
On MySQL 5.5.20 with InnoDB tables i've reproduced your situation in a simplified test.
both, inserting using a result from the trigger table which is referring to the new row alreay and directly inserting using the NEW values worked fine
CREATE TABLE test1(a1 INT NOT NULL auto_increment, b1 INT, PRIMARY KEY (a1) );
CREATE TABLE test2(a1 INT, b1 INT);
CREATE TABLE test3(a1 INT, b1 INT);
DELIMITER ;;
CREATE TRIGGER testAI AFTER INSERT ON test1
FOR EACH ROW BEGIN
INSERT INTO test2 SET a1 = NEW.a1, b1 = NEW.b1;
INSERT INTO test3 ( a1, b1 ) SELECT a1, b1 FROM test1 WHERE a1 = NEW.a1;
END;
;;
DELIMITER ;
Fire the trigger
INSERT INTO test1 (b1) VALUES (1),(2),(3);
Directly inserted from NEW values
mysql> SELECT * FROM test2;
+------+------+
| a1 | b1 |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+
3 rows in set (0.00 sec)
Inserted from SELECT result
mysql> SELECT * FROM test3;
+------+------+
| a1 | b1 |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+------+------+
3 rows in set (0.00 sec)
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.5.20 |
+-----------+
1 row in set (0.00 sec)
So this works for both auto_increment and explicitly inserted values.
Your problem must be somewhere else

Enforce order on composite primary key

Say I have the following table
item_a_id, item_b_id, value
Where item_a_id and item_b_id are a composite primary key. In my example a,b and b,a are equivalent. Therefore I want to ensure that item_a_id < item_b_id. Obviously the application logic will enforce this but is there a way to ensure the database does too?
In a reasonably current version of MySql you can use triggers to emulate a check constraint that produces the desired behavior.
Well, in your case, you could use trigger to check values before insert/update and swap it to ensure item_a_id will always less than item_b_id.
Assuming the table name is item_links, you could try this:
DELIMITER |
CREATE TRIGGER ensure_a_b_before_insert BEFORE INSERT ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET #tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = #tmp;
END IF;
END;
|
CREATE TRIGGER ensure_a_b_before_update BEFORE UPDATE ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET #tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = #tmp;
END IF;
END;
|
DELIMITER ;
Here's what I got when I test inserting:
mysql> INSERT INTO `item_links` (`item_a_id`, `item_b_id`, `value`)
-> VALUES ('1', '2', 'a')
-> , ('3', '2', 'b')
-> , ('4', '1', 'c');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 1 | 2 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)
Update works, too:
mysql> UPDATE `item_links`
-> SET `item_a_id` = 100, `item_b_id` = 20
-> WHERE `item_a_id` = 1 AND `item_b_id` = 2;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 20 | 100 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)

Set iterative values in rows of a table

I have the following table
id name address empid
1 AA aa 0
2 BB bb 0
3 CC cc 0
I need to write a query to set empid starting from 1. How to write it please. Do i have to use a stored procedure to that or can do it with a normal query?
Thank You.
Here is a way to do it that utilizes a pretty obscure assignment operator in MySQL. This solution won't skip numbers in the case of gaps in the primary key sequence like some of the other solutions.
set #count = 0;
update test set empid = #count := #count+1;
Here is the proof:
mysql> create table test (
-> id int unsigned primary key auto_increment,
-> name varchar(32) not null,
-> address varchar(32) not null,
-> empid int unsigned not null default 0
-> ) engine=innodb;
Query OK, 0 rows affected (0.02 sec)
mysql> insert into test (name, address)
-> values ('AA', 'aa'), ('BB', 'bb'), ('CC', 'cc');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from test;
+----+------+---------+-------+
| id | name | address | empid |
+----+------+---------+-------+
| 1 | AA | aa | 0 |
| 2 | BB | bb | 0 |
| 3 | CC | cc | 0 |
+----+------+---------+-------+
3 rows in set (0.00 sec)
mysql> set #count=0;
Query OK, 0 rows affected (0.00 sec)
mysql> update test set empid = #count := #count+1;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3 Changed: 3 Warnings: 0
mysql> select * from test;
+----+------+---------+-------+
| id | name | address | empid |
+----+------+---------+-------+
| 1 | AA | aa | 1 |
| 2 | BB | bb | 2 |
| 3 | CC | cc | 3 |
+----+------+---------+-------+
3 rows in set (0.00 sec)
If you are looking to put 1 in empid for the first row, 2 for the second, etc. the easiest way would be to use your id field that is already doing this like so:
UPDATE table
SET empid = id
The only thing you need to worry about is missing numbers in the id column. If that would be an issue and you are missing id numbers, you will have to use a different method. To do that, you would need to do something like this:
DECLARE #counter int
SET #counter = 1
UPDATE table
SET #counter = empid = #counter + 1
As #BiggsTRC suggested you can use id to set empid. If not, you can create stored procedure or some PHP code to do that.
If your ID is not "AutoIncrement" field, you can consider a new column as autoincrement field and assign that value to emp with update query and later delete that new column. (These are some alternates, you need to choose the best one)
UPDATE `test` SET `empid`=`id`
But why would you want to do it? It's pretty much definition of redundancy.