Cross database trigger in Mysql - mysql

Is it possible to apply trigger for cross database access in MySQL If so please give one example. My purpose is to insert/update/delete data in database2 if there is any new data inserted/updated/deleted in database1. I am using MySQL 5.1

I know it is an old topic but I just had to implement a cross-database trigger myself and I would like to show the solution here as other readers might benefit from it.
Inside the code of the trigger it is possible to refer to the target database with its full name database_name.table_name.
Suppose you have two databases on the same server: database1 and database2. In each of the two databases you have the following table:
CREATE TABLE 'test' (
'id' int(10) DEFAULT NULL,
'name' varchar(100) DEFAULT NULL
)
In the database1 you create the following INSERT trigger:
USE database1;
DELIMITER //
CREATE TRIGGER sync_insert AFTER INSERT ON test
FOR EACH ROW
BEGIN
INSERT INTO database2.test SET id = NEW.id, name=NEW.name;
END; //
DELIMITER ;
Define similar triggers for UPDATE and DELETE.
I'd say this solution is more simple and straightforward than using procedures.
I tested the above on MySQL 5.1.73 and MariaDB 10.2.13.

Yes, you can. You could make a procedure and call it in your trigger. Procedure example :
DELIMITER //
CREATE PROCEDURE delete(in table VARCHAR(300), in db VARCHAR(300), in id INT)
BEGIN
set #query0 = CONCAT('DELETE FROM ', new_db, '.', tabela, ' WHERE id=',id);
PREPARE select_query0 FROM #query0;
EXECUTE select_query0;
DEALLOCATE PREPARE select_query0;
END; //
DELIMITER ;
And then to create the trigger:
CREATE TRIGGER del_trigger BEFORE DELETE ON table
FOR EACH ROW BEGIN
CALL delete(db, table, OLD.id);
END;

Related

stored procedure returning `ASCII \0` error but can't find what that is referring to

I am writing my first stored procedure as a trigger. I am doing this in a dev migration as we have two systems which don't speak to each other in dev, so I need to mock the data which would normally come from the other system.
My procedure is added as part of our dev migration script.
DELIMITER |;
CREATE TRIGGER `activity_insert` AFTER INSERT ON `activity`
FOR EACH ROW
BEGIN
UPDATE `activity` AS `a` JOIN `handle` AS `h` on `a.handle_id` = `h.handle_id` SET `path` = CONCAT(`h.handle`,'/',`a.activity_handle`) WHERE `a.path` IS NULL;
END;
|
DELIMITER;
I would expect the logic to be:
DELIMITER $$
CREATE TRIGGER activity_insert BEFORE INSERT ON activity
FOR EACH ROW
BEGIN
IF new.path IS NULL THEN
SET new.path = (SELECT CONCAT(h.handle, '/', new.activity_handle)
FROM handle h
WHERE new.handle_id = h.handle_id
);
END IF;
END;$$
DELIMITER;
There are numerous problem with your code:
You don't update the table being modified using update.
You want a "before" triggers, not an "after trigger".
Don't use | for the the delimited. It is a valid MySQL operator.
You have over-used the backtick, including putting the table alias in with the column alias.
This assumes that handle.handle_id is unique. This seems like a reasonable assumption based on the names, but you can add limit 1 to guarantee no more than one row is returned.

Update MySQL database table schema

I want to update a MySQL database schema (with MySQL code) but I am unfortunately not sure of the state of the tables, as they are distributed..
Let's say some 'clients' have a table called "user" with a schema like
name VARCHAR(64) NOT NULL
password VARCHAR(64) NOT NULL
I want to add an email column, but it's possible that they already have an email column (depending on their installation version).
How can I run a command that ensures that there is a email column and does nothing if it's already there? Keep in mind I would be doing this for many tables that are more complex.
I know I could be creating temp tables and re-populating (and will if it's the only solution) but I figure there might be some kind of CREATE or UPDATE table command that has "oh you already have that column, skip" logic.
You can try like this:
DELIMITER $$
CREATE PROCEDURE Alter_MyTable()
BEGIN
DECLARE _count INT;
SET _count = ( SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'user' AND
COLUMN_NAME = 'email');
IF _count = 0 THEN
ALTER TABLE user
ADD COLUMN email varchar(512);
END IF;
END $$
DELIMITER ;
or rather make it a generic stored procedure like this:
create procedure AddColumnIfDoesntExists(
IN dbName tinytext,
IN tableName tinytext,
IN fieldName tinytext,
IN fieldDef text)
begin
IF NOT EXISTS (
SELECT * FROM information_schema.COLUMNS
WHERE column_name=fieldName
and table_name=tableName
and table_schema=dbName
)
THEN
set #ddl=CONCAT('ALTER TABLE ',dbName,'.',tableName,
' ADD COLUMN ',fieldName,' ',fieldDef);
prepare stmt from #ddl;
execute stmt;
END IF;
end;
//
delimiter ';'
If the column already exists the ALTER TABLE ADD COLUMN statement will throw an error, so if you are thinking that you might lose data because of trying to add a column that already exists that won't be the case, if any you need to handle error. See add column to mysql table if it does not exist
There are also resources telling you how to deal with these with store procedures, etc. See MySQL add column if not exist.
Hope it helps.

PhpMyAdmin, where procedures are saved on filesystem

I want to create procedure in mysql over phpmyadmin which insert paramters in two tables but phpmyadmin throws error that this is not possible.
So i want to try edit procedures over notepad++. Can you please tell me where are they saved on file system.
I run phpmyadmin on localhost with xampp.
Or if any other option to create procedure with this two insert statement.
INSERT INTO `table1`(`att1`, `att2`, `att3`)
VALUES (p_att1, p_att2, p_att3);
INSERT INTO `table2`(`att1`, `att2`, `att3`, `att4`, `att5`)
VALUES ('admin','admin', p_att4, p_att5, p_att6)
As already mentioned in comments stored procedures are not stored on the filesystem but rather in a special table in a database itself.
If you have appropriate permissions you can see a procedure's definition by issuing the following command
SHOW CREATE PROCEDURE my_proc;
Now your procedure can look like this
DELIMITER $$
CREATE PROCEDURE my_proc
(
IN _att1 VARCHAR(32),
IN _att2 VARCHAR(32),
IN _att3 VARCHAR(32),
IN _att4 VARCHAR(32),
IN _att5 VARCHAR(32)
)
BEGIN
START TRANSACTION;
INSERT INTO table1(att1, att2, att3)
VALUES (_att1, _att2, _att3);
INSERT INTO table2(att1, att2, att3, att4, att5)
VALUES ('admin','admin', _att3, _att4, _att5);
COMMIT;
END$$
DELIMITER ;
Here is SQLFiddle demo

Setting up a trigger in PHPMyAdmin

I'm trying to comprehend triggers, and I think I fully understand them, but I haven't been able to implement any of them. I want this code to delete a user with the name "test". So if anyone updates their name to "test" the user should be deleted.
My example code:
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_db` FOR EACH ROW
BEGIN
DELETE FROM my_table WHERE `username` = 'test';
END
My 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 '' at line 4
I can't figure out why the delete statement is giving me an error. Any ideas?
Here is the syntaxically correct SQL:
DELIMITER ;
DROP TRIGGER IF EXISTS `my_trigger`;
DELIMITER $$
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_table` FOR EACH ROW
BEGIN
DELETE FROM my_table WHERE `username` = 'test';
END$$
DELIMITER;
But it won't work, because you can't delete from the table, you are updating:
A trigger can access both old and new data in its own table. A trigger
can also affect other tables, but it is not permitted to modify a
table that is already being used (for reading or writing) by the
statement that invoked the function or trigger.
http://dev.mysql.com/doc/refman/5.5/en/faqs-triggers.html#qandaitem-B-5-1-9
If you want a simple example, try this:
DELIMITER ;
DROP TRIGGER IF EXISTS `my_trigger`;
DELIMITER $$
CREATE TRIGGER `my_trigger`
BEFORE UPDATE ON `my_table` FOR EACH ROW
BEGIN
SET NEW.`username` = 'aaa';
END$$
DELIMITER;
This will always set 'aaa' as the user name when updating.
It's possible to associated trigger only with a table.
Also within a stored function or trigger, it is not permitted to modify a table that is already being used (for reading or writing) by the statement that invoked the function or trigger.
Restrictions on Stored Programs

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.