views:

28

answers:

2

I have a situation in which I don't want inserts to take place (the transaction should rollback) if a certain condition is met. I could write this logic in the application code, but say for some reason, it has to be written in MySQL itself (say clients written in different languages will be inserting into this MySQL InnoDB table) [that's a separate discussion].

Table definition:

CREATE TABLE table1(x int NOT NULL);

The trigger looks something like this:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    NEW.x = NULL;
  END IF;
END;

I am guessing it could also be written as(untested):

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    ROLLBACK;
  END IF;
END;

But, this doesn't work:

CREATE TRIGGER t1 BEFORE INSERT ON table1 ROLLBACK;

You are guaranteed that:

  1. Your DB will always be MySQL
  2. Table type will always be InnoDB
  3. That NOT NULL column will always stay the way it is

Question: Do you see anything objectionable in the 1st method?

A: 

Have you tried raising an error to force a rollback? For example:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW
  IF (condition) THEN
    SELECT 1/0 FROM table1 LIMIT 1
  END IF;
END;
Eric Petroelje
MySQL doesn't expose the ability for custom errors :/
OMG Ponies
This fails with the error "Not allowed to return a result set from a trigger"
dhruvbird
+1  A: 

From the trigger documentation:

The trigger cannot use statements that explicitly or implicitly begin or end a transaction such as START TRANSACTION, COMMIT, or ROLLBACK.

Your second option couldn't be created. However:

Failure of a trigger causes the statement to fail, so trigger failure also causes rollback.

So Eric's suggestion to use a query that is guaranteed to result in an error is the next option. However, MySQL doesn't have the ability to raise custom errors -- you'll have false positives to deal with. Encapsulating inside a stored procedure won't be any better, due to the lack of custom error handling...

If we knew more detail about what your condition is, it's possible it could be dealt with via a constraint.

Update


I've confirmed that though MySQL has CHECK constraint syntax, it's not enforced by any engine. If you lock down access to a table, you could handle limitation logic in a stored procedure. The following trigger won't work, because it is referencing the table being inserted to:

CREATE TRIGGER t1 BEFORE INSERT ON table1
FOR EACH ROW

  DECLARE num INT;
  SET num = (SELECT COUNT(t.col)
              FROM your_table t
             WHERE t.col = NEW.col);

  IF (num > 100) THEN
    SET NEW.col = 1/0;
  END IF;

END;

..results in MySQL error 1235.

OMG Ponies
So I basically want to limit the number of rows for a certain key.So if the table is (id, name, entry), I want to limit the number of rows that each name can occupy. i.e. I want to limit the number of times any name can occur to a maximum of 100 (say).So, if I have 100 occurances of name "hello", then no one should be able to insert any entry with name == "hello"
dhruvbird