Why opposite operation <> doesn't work on trigger? - mysql

I have a trigger which is AFTER UPDATE. I have a condition in that which doesn't work, How can I fix it?
$$
BEGIN
IF NEW.colname <> OLD.colname THEN
DELETE FROM tableX WHERE id = OLD.id;
END IF;
END
$$
It should be noted if I write this IF 1 THEN then that DELETE query works. So the problem is that condition. What's wrong with it?
As #Darwin von Corax said in the comments, when one of these NEW.colname, OLD.colname is null, then all of that condition returns false. So I want to know how can I create a condition which acts like this ?
Null <> 10 -- true
Null <> Null -- false
10 <> 12 -- true
32 <> Null -- true
3 <> 3 -- false

If either NEW.colname or OLD.colname is null, then <> will return null which if would treat the same as false.
Fortunately, there is a solution: the <=> (NULL-safe equality) operator, which returns 1 if both operands are null and 0 if only one is. The expression
IF NOT (NEW.colname <=> OLD.colname) THEN
should do what you need.

Just add logic for checking null conditions. It is not triggered when both columns are null which means that no changes happen.
$$
BEGIN
IF
-- when exactly one of the column is null
NEW.colname is not null and OLD.colname is null or
NEW.colname is null and OLD.colname is not null or
-- when both are not null compare their values
NEW.colname is not null and OLD.colname is not null and NEW.colname <> OLD.colname THEN
DELETE FROM tableX WHERE id = OLD.id;
END IF;
END
$$

Related

mysql trigger on update: how to detect NULL values?

I try to update the porcentageComplete profil when users updates his profile:
statut field:
`statut` enum('Marié','En couple','Divorcé') DEFAULT NULL,
Trigger is:
DROP TRIGGER IF EXISTS update_user;
DELIMITER $$
CREATE TRIGGER update_user
BEFORE UPDATE
ON users FOR EACH ROW
BEGIN
DECLARE porcentage int default 0;
IF NEW.statut!=NULL OR OLD.statut!=NULL THEN
set porcentage = porcentage + 1;
END IF;
SET NEW.porcentageCompleted = porcentage;
END$$
This not update correctly the porcentageCompleted : it looks like NULL comparaison does not work correctly
Comparisons with = or <>(or !=) to a NULL value yield NULL themselves, so not true, i.e. false. Use IS NULL and IS NOT NULL to check for NULLs.
...
IF NEW.statut IS NOT NULL
OR OLD.statut IS NOT NULL THEN
...
Worth a read: 3.3.4.6 Working with NULL Values

MySQL Trigger not entirely working

my trigger is coming back with no errors. But when i test it, no error message is returned and the test data is stored in the table.. Which isn't what I want.
Basically (this is for coursework), I want a trigger that displays an error message when a location other than Barcelona is inserted into the table.
This is my trigger. As I said, no errors come back, but it doesn't work?
DELIMITER $$
CREATE TRIGGER after_location_insert_finance
AFTER INSERT ON Finance
FOR EACH ROW
BEGIN
DECLARE LocationTrigger varchar(255);
DECLARE msg varchar(255);
SELECT Location INTO LocationTrigger
FROM Finance
WHERE Location != "Barcelona";
IF(LocationTrigger != "Barcelona") THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Not a valid location';
END IF;
END$$
The expression in the IF won't evaluate to TRUE if LocationTrigger is null.
And LocationTrigger will be NULL if there are not rows in Boss that satisfy the condition in the WHERE clause.
I'm not understanding why there's no check of the value being inserted into the location column; or why are we running a query of the Boss table, when we're comparing to literal value of 'Barcelona'.
Seems like we'd want this kind of check in a BEFORE trigger rather than an AFTER trigger.
Are we going to allow NULL values for location?
If the only value we allow to be inserted for location is 'Barcelona', and if we aren't allowing NULL values, then we don't need to mess with any query of the Boss table. Just do a comparison...
BEGIN
IF NOT ( NEW.location <=> 'Barcelona' ) THEN
SIGNAL ...
END IF;
END
Maybe the goal of the trigger is to enforce a referential integrity constraint (which we'd normally implement by declaring a FOREIGN KEY constraint, rather than implementing a procedure.)
Assuming that a "valid" location is defined by the domain of location values in Boss table,
and assuming we aren't going to allow NULL values, then:
BEGIN
DECLARE ls_location VARCHAR(255) DEFAULT NULL;
-- check if the value being inserted exists in a lookup table
SELECT b.location INTO ls_location
FROM Boss b
WHERE b.location = NEW.location
LIMIT 1
;
-- if we didn't find a match, ls_location will be NULL
IF ls_location IS NULL THEN
SIGNAL ...
END IF;
END
If no matching row is found in Boss, then ls_location will be NULL.
A "not equals" comparison to NULL is going to evaluate to NULL, not TRUE or FALSE.
Boolean logic is SQL is tri-valued... TRUE, FALSE and NULL
SELECT 0 = 1 AS c0
, 0 <> 1 AS c1
, 0 = NULL AS c2
, 0 <> NULL AS c3
, NULL = NULL AS c4
, NULL <> NULL AS c5

SQL Trigger After Update not working

please help me...
USE `arma3life`;
DELIMITER $$
CREATE DEFINER=`zoxxen`#`localhost` TRIGGER `money_log` AFTER UPDATE ON `players` FOR EACH ROW
BEGIN
IF NEW.`bankacc` <> OLD.`bankacc` OR NEW.`cash` <> OLD.`cash` THEN
INSERT INTO `supportertool_money` (
`i_player_id`
,`i_bankacc`
,`i_cash`
,`dt_inserted`
)
VALUES (
NEW.`playerid`
,NEW.`bankacc`
,NEW.`cash`
,NOW()
);
END IF;
END $$
DELIMITER ;
There have to be a issue.. I cant Update my rows anymore and the Trigger is not working
I'm using innodb
Your if statement is:
IF NEW.`bankacc` <> OLD.`bankacc` OR NEW.`cash` <> OLD.`cash` THEN
The conditions do not do what you expect when values are NULL. Try this:
IF NEW.bankacc <> OLD.bankacc OR
NEW.bankacc is null and OLD.bankacc is not null or
NEW.bankacc is not null and OLD.bankacc is null or
NEW.cash <> OLD.`cash` or
NEW.cash is null and OLD.cash is not null or
NEW.cash is not null and OLD.cash is null then

Comparison in mysql Trigger for Null Value

This is my trigger after update record.
The old.ActivatedDate always is Null and new.ActivatedDate always is not Null.
This is my code, but it is not working because its condition is not returning true to continue other jobs.
SET #OldActivateDate := OLD.ActivateDate;
SET #NewActivateDate := NEW.ActivateDate;
IF(#NewActivateDate IS NOT NULL AND #OldActivateDate IS NULL AND #OldActivateDate!=#NewActivateDate)
THEN
/* Do Some Functionality */
END IF;
I tested this method also, but again it is not working.
if (#NewActivateDate != #OldActivateDate) and ( #NewActivateDate is not null and #OldActivateDate is null )
THEN
/* Do Some Functionality */
END IF;
If you want to check that old.ActiveDate should be NULL and new.ActivateDate should not be NULL, then why do you have other conditions. Just use:
IF (#NewActivateDate IS NOT NULL AND #OldActivateDate IS NULL) THEN
. . .
END IF

MySQL Trigger checking for existing rows with possible NULL values

I have an InnoDB table with a unique index on performance_id, ticket_rank_id and ticket_type_id.
All of these id's have relations to other tables, but their values can also be NULL.
MySQL allows duplicate rows if one of the column values is NULL so I decided to build a trigger for this problem.
CREATE TRIGGER `before_insert_performance_tickets`
BEFORE INSERT ON `performance_tickets` FOR EACH ROW BEGIN
DECLARE num_rows INTEGER;
SELECT COUNT(*) INTO num_rows FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND ticket_rank_id = NEW.ticket_rank_id
AND ticket_type_id = NEW.ticket_type_id;
IF num_rows > 0 THEN
// Cancel insert action
ELSE
// Perform insert action
END IF;
END
The problem is AND ticket_rank_id = NEW.ticket_rank_id where I have to check if ticket_rank_id is NULL or has a value.
AND ticket_rank_id = NULL does not work, it only works if i do AND ticket_rank_id IS NULL.
Is there any slick solution for this or do I have to write separate queries depending on NEW.ticket_rank_id and NEW.ticket_type_id being NULL or not?
You need to add extra OR condition for NULL values (ticket_rank_id IS NULL OR ticket_rank_id = NEW.ticket_rank_id) because NULL compared with anything return FALSE. Try this query:
SELECT COUNT(*)
INTO num_rows
FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND (ticket_rank_id IS NULL OR ticket_rank_id = NEW.ticket_rank_id)
AND (ticket_type_id IS NULL OR ticket_type_id = NEW.ticket_type_id);
I think I figured it out:
SELECT COUNT(*) INTO num_rows FROM performance_tickets
WHERE performance_id = NEW.performance_id
AND IF(NEW.ticket_rank_id IS NULL, ticket_rank_id IS NULL, ticket_rank_id = NEW.ticket_rank_id)
AND IF(NEW.ticket_type_id IS NULL, ticket_type_id IS NULL, ticket_type_id = NEW.ticket_type_id)
Seems to work, now I have to figure out how to abort the insert if num_rows == 1. But that's a different problem.
Thanks anyways ;)