I need to create a stored function which disables triggers on demand.
At first I have a parameter #disable_triggers which can I set to "all" or to specific trigger name. In the trigger I would have a variable which I assign to procedures return value and if it's true I don't execute trigger code. So in procedure I need to somehow handle the case with specific trigger name.
CREATE PROCEDURE `DisableTriggers`()
BEGIN
IF(#disable_triggers = 'all') THEN
RETURN 1;
END IF;
IF (#disable_triggers CONTAINS 'Specific trigger name') THEN
Return true to disable specific trigger. <<-- how to return it here.
END IF;
END
So the question I ask is how to handle the case with specific triggers what to return.
In general there is no way to disable triggers in MySQL/MariaDB.
You can only delete triggers and re-create them later but be aware of MDL locks if you have high loaded environment.
Still you have an option to do some tricks with session variables like MySQL disable all triggers
Related
I am trying to create an after insert trigger in MySQL that writes the message "Insert Failed" to an error table called tbl_error if the trigger fails for any reason.
To solve this problem, I have attempted to use a combination of handlers and signal statements. None have worked.
DELIMITER $$
CREATE TRIGGER trig_statesout_afterinsert AFTER INSERT ON states
FOR EACH ROW
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
SIGNAL SQLSTATE VALUE '99999'
SET MESSAGE_TEXT = 'Insert Failed';
INSERT INTO tbl_error(ErrorMessage) Values ('Insert Failed');
END;
INSERT INTO statesout (states_id, state, cases, lastupdate)
SELECT s.states_id, s.state, s.cases, current_timestamp()
FROM states as s
WHERE s.states_id = NEW.states_id;
END $$
I attempted to return information from a diagnostic statement, but that didn't work either.
Because the documentation states that
For SQLEXCEPTION conditions, the stored program terminates at the
statement that raised the condition, as if there were an EXIT handler.
If the program was called by another stored program, the calling
program handles the condition using the handler selection rules
applied to its own handlers.
I split the update logic for the trigger into a separate stored procedure in case the issue was that the SQLEXCEPTION conditions cannot be in the calling object. It didn't work.
Some SO solutions suggest using a "trick" to call a nonexistent table, but the documentation says this is not necessary due to the SIGNAL statement:
Without SIGNAL, it is necessary to resort to workarounds such as
deliberately referring to a nonexistent table to cause a routine to
return an error.
In any case, those solutions only throw errors based on a specific condition, not for any condition.
What am I doing wrong? Is it impossible for a MYSQL trigger to return an error message if the trigger fails for any reason?
It's not possible to make any change to data if the trigger activates a SQLException.
If the trigger experiences any error, whether handled or not handled, then the INSERT that spawned the trigger is undone, as well as any SQL run by the trigger, and even any SQL run by triggers spawned by actions your trigger executes.
This is related to the idea of atomicity — either the whole action must succeed, or else no part of the action is saved. It's all or nothing.
If you want to log the error, you'll have to check for the error in your application, and then log the error as a separate action. You can't do it in the trigger body.
I created some triggers to make some simple validations. I covered the before insert scenario, for example:
CREATE TRIGGER TR_before_insert_login
BEFORE INSERT ON login
FOR EACH ROW
BEGIN
IF (CHAR_LENGTH(NEW.password) < 4 OR CHAR_LENGTH(NEW.password) > 10) THEN
SIGNAL SQLSTATE '42000'
SET MESSAGE_TEXT = 'password must be between 4 e 10 characters';
END IF;
......
But if the user performs an update I can't prevent it from entering incorrect data. Do I need to create a before update and duplicate my validation code or there is a better way to do this.
Why don't put the logic (your validation code) into procedure and execute it inside the separate triggers (insert/update).
-- pseudo code
create procedure PASSWORD_VALIDATION(_psswd) { /* validation */ };
create trigger table_ub BEFORE UPDATE { CALL PASSWORD_VALIDATION(NEW.password);};
create trigger table_ib BEFORE INSERT { CALL PASSWORD_VALIDATION(NEW.password);};
Thus, your validation code is not duplicated.
ALTER TRIGGER [dbo].[trigger_name]
ON [dbo].[table_name]
FOR DELETE, INSERT, UPDATE
AS
BEGIN
'your code here'
END
you can use structure like this to call same trigger for insert,update and delete
For test correctness of query I need disable all triggers in db.
I see that in information_schema exists table TRIGGERS.
Is possible temporarily disable all triggers using this table?
E.g. like:
update TRIGGERS set TRIGGERS_SCHEMA='myschema_new'
where TRIGGERS_SCHEMA='myschema'
and after finish all test return all triggers like:
update TRIGGERS set TRIGGERS_SCHEMA='myschema'
where TRIGGERS_SCHEMA='myschema_new'
May be this can corrupt db or after triggers will not works? I didn't found about it in documentation.
You can't disable triggers directly and I wouldn't recommend doing what you're suggesting but you could have your trigger check if a variable (in my example below #disable_triggers) is NULL before executing the trigger's content. For example:
Query:
SET #disable_triggers = 1;
// Your update statement goes here.
SET #disable_triggers = NULL;
Triggers:
IF #disable_triggers IS NULL THEN
// Do something use as the trigger isn't disabled.
END IF;
It is not possible to 'disable' triggers in mysql, however a trick that can be used to get around this
Add a condition in your triggers like:
if (DISABLE_TRIGER <> 1 ) then
#trigger body
end if;
and than if you want to disable triggers on import just:
SET #DISABLE_TRIGER = 1;
do imports
SET #DISABLE_TRIGER = 0;
Does MySQL permit callbacks in C such that when a change happens in the database, like an insert, that is performed by a different program or by the user at the command line, I can be notified?
I am guessing that it doesn't, because mysqlclient is a library, not a running thread. But I may as well ask.
Create a trigger like so.
DELIMITER $$
CREATE TRIGGER ad_mytable_each AFTER DELETE ON MyTable FOR EACH ROW
BEGIN
#write code that trigger After delete (hence the "ad_" prefix)
#For table MyTable (The _MyTable_ middle)
#On each row that gets inserted (_each suffix)
#
#You can see the old delete values by accesing the "old" virtual table.
INSERT INTO log VALUES (old.id, 'MyTable', old.field1, old.field2, now());
END$$
DELIMITER ;
There are triggers for INSERT, DELETE, UPDATE
And they can fire BEFORE or AFTER the action.
The trigger BEFORE the action can cancel the action by forcing an error, like so.
CREATE TRIGGER bd_mytable_each BEFORE DELETE ON MyTable FOR EACH ROW
BEGIN
#write code that trigger Before delete (hence the "db_" prefix)
declare DoError Boolean;
SET DoError = 0;
IF old.id = 1 THEN SET DoError = 1; END IF;
IF (DoError = 1) THEN SELECT * FROM Table_that_does_not_exist_to_force_error;
#seriously this example is in the manual.
END$$
DELIMITER ;
This will prevent deletion of record 1.
A before UPDATE Trigger can even change the values updated.
CREATE TRIGGER bu_mytable_each BEFORE UPDATE ON MyTable FOR EACH ROW
BEGIN
IF new.text = 'Doon sucks' THEN SET new.text = 'Doon rules';
END$$
DELIMITER ;
Hope you'll be Trigger happy.
MySQL's triggers allow you to hook into insert/update/delete queries and do something additional. You could log them in a separate table, for example.
Well you could attach a trigger to user defined function, and have it call an external program, that would then notify your code..
http://dev.mysql.com/doc/refman/5.0/en/faqs-triggers.html#qandaitem-B-5-1-10
You can use triggers combined with UDFs (user defined functions) so that the corresponding action on the database executes a trigger that calls a C/C++ function.
Just consider that this mechanism runs your code inside the mysql server process, not in the client side.
I am working on MySQL 5.1.3 and using PHPMyAdmin 3.1.3.1 to access it. With PHP as the Server side scripting Language. My problem statement is can we call a Stored Procedure or Function from the Trigger statement so that when ever an INSERT|UPDATE|DELETE trigger is called, it calls the SP for updating some other tables according to the logic defined.
Look here Mysql Trigger Syntax
mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
-> FOR EACH ROW
-> BEGIN
-> IF NEW.amount < 0 THEN
-> SET NEW.amount = 0;
-> ELSEIF NEW.amount > 100 THEN
-> SET NEW.amount = 100;
-> END IF;
-> END;//
mysql> delimiter;
It can be easier to define a stored procedure separately and then invoke it from the trigger using a simple CALL statement. This is also advantageous if you want to invoke the same routine from within several triggers.
There are some limitations on what can appear in statements that a trigger executes when activated:
The trigger cannot use the CALL statement to invoke stored procedures that return data to the client or that use dynamic SQL. (Stored procedures are permitted to return data to the trigger through OUT or INOUT parameters.)
The trigger cannot use statements that explicitly or implicitly begin or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK.