Question

I am developing a program that uses a MySQL database to store data. I have a table (simplified here):

+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| dataId  | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| someNum | tinyint(4)       | NO   |     | 0       |                |
+---------+------------------+------+-----+---------+----------------+

Now, I update the table with a query like this one.

UPDATE table SET someNum=someNum+2 WHERE dataId=78225;

The ID and the amount someNum changes come dynamically from code.

Now, what I'd like to do is limit someNum's value to between -3 and 3, particularly in that UPDATE. It isn't required, my software can handle it being outside that range, but the data would be clearer with that limit. If someNum+2 would be over 3, I'd just like to set it to 3.

Numeric MIN/MAX would make it easy:

UPDATE table SET someNum=MAX(-3,MIN(3,someNum+2)) WHERE dataId=78225;

I looked at the docs here, but there seems to be no MIN/MAX for numbers. MIN and MAX are found here, but they don't seem to be the right ones for this.

What would be the best way (if any) to implement such a limit in MySQL (not the code that calls MySQL)?

Was it helpful?

Solution

First way: use LEAST() and GREATEST():

UPDATE t SET someNum=GREATEST(-3,LEAST(3,someNum+2)) WHERE dataId=78225;

This is the most easy way because you'll store all the logic inside one UPDATE query.

Second way: create trigger:

DELIMITER //
CREATE TRIGGER catCheck BEFORE UPDATE ON t
    FOR EACH ROW
    BEGIN
        IF NEW.someNum<-3 THEN
           NEW.someNum=-3;
        END IF;

        IF NEW.someNum>3 THEN
           NEW.someNum=3;
        END IF;
    END;//
DELIMITER ;

you can also replace IF with CASE - but I left that two separate constraints for -3 and 3. The benefits here is - that DBMS will handle your data by itself - and you'll be able to pass data as it is and do not worry about ranges. But - there's weakness too: while in first case you can just change query text to adjust desired range, in second case you'll have to re-create trigger again if you'll want to change that constraints (so, less flexibility).

Also you may want to check your data not only on UPDATE statements, but on INSERT too.

OTHER TIPS

The appropriate functions in MySQL are greatest() and least(), not max()/min(). But, I think it is clearer with just a case statement:

UPDATE table
    SET someNum = (case when someNum + 2 < -3 then -3
                        when someNum + 2 > 3 then 3
                        else someNum + 2
                   end) 
   WHERE dataId=78225;

use GREATEST and LEAST instead of MAX and MIN

You could also use a CASE WHEN

update table
set someNum = CASE WHEN SomeNum +2 > 3 THEN 3 
                   WHEN SomeNum +2 < -3 THEN -3
                   ELSE someNum + 2
              END)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top