2015-11-10 4 views
2

Итак, у меня есть таблица примерно следующим образом:MySQL Insert/Update Триггер с AUTO_INCREMENT

CREATE TABLE CUSTOMER (
    CUSTID    INT NOT NULL AUTO_INCREMENT, 
    NAME    CHAR (45), 
    CONSTRAINT CUSTOMER_PRIMARY_KEY PRIMARY KEY (CUSTID)) 
AUTO_INCREMENT = 100; 

Я авто приращением CUSTID так что можно просто вставить имя и он создан следующий доступный CUSTID. Тем не менее, я также хочу, чтобы убедиться, что это не представляется возможным установить значение CUSTID нулю, либо о создании строки или на обновление, так что я построил следующий триггер:

DELIMITER $$ 
CREATE TRIGGER `custid_before_insert` BEFORE INSERT ON `CUSTOMER` 
FOR EACH ROW 
BEGIN 
    IF (NEW.CUSTID) <= 0 THEN 
     SIGNAL SQLSTATE '12345' 
      SET MESSAGE_TEXT = 'Check constraint on CUSTOMER.CUSTID failed'; 
    END IF; 
END$$ 

CREATE TRIGGER `custid_before_update` BEFORE UPDATE ON `CUSTOMER` 
FOR EACH ROW 
BEGIN 
    IF (NEW.CUSTID) <= 0 THEN 
     SIGNAL SQLSTATE '12345' 
      SET MESSAGE_TEXT = 'Check constraint on CUSTOMER.CUSTID failed'; 
    END IF; 
END$$ 
DELIMITER ; 

К сожалению, в мой блаженный незнание того, как работал AUTO_INCREMENT, я пришел к выводу, что это неправильный путь. Попытка вставить клиента без значения CUSTID - это отключение триггера, что приводит к сбою вставки, которое, как я полагаю, связано с тем, что значение равно нулю перед вставкой, когда AUTO_INCREMENT присваивает ему значение.

Будет ли лучший способ сделать это, действительно, изменить триггер, чтобы произойти после вставки и удаления строки, или есть лучший способ сделать это, чтобы просто выбросить ошибку?

+0

Обычно для этого используется ограничение CHECK, например 'CHECK (custid> 0)' but ... "* Предложение CHECK анализируется, но игнорируется всеми механизмами хранения. *" Если нет особых причин для бизнеса идентификатор не может быть 0, нет причины целостности данных, чтобы запретить его. – Schwern

+0

Должен любить MySQL, да? К сожалению, моя спецификация заключается в том, что идентификатор никогда не может быть ниже 1. Первоначальные Postgres, которые я переношу, фактически используют проверку точно так же, как вы предложили, которая работает нормально, но я изо всех сил пытаюсь сделать то же самое с MySQL. – Jamie4840

ответ

2

Вставить триггер не требуется.

От Auto_Increment

Ни одно значение не было задано для столбца AUTO_INCREMENT, поэтому MySQL назначены порядковые номера автоматически. Вы также можете явно указать в столбце для генерации порядковых номеров.

E.G.

create table t(id int auto_increment, primary key(id)); 
insert into t(id) values (0); 
select id from t; 
# 1 

Update:

Чтобы разрешить вставку для завершения, когда CUSTID не указано,

INSERT INTO customer(name) VALUES('Chuck'); 

проверка нуль в триггер:

IF NEW.CUSTID IS NOT NULL AND NEW.CUSTID <= 0 THEN 
+0

Извлечение триггера вставки, конечно, избавляется от ошибки, но это своего рода поражение объекта. Я все еще могу сделать вставку 'CUSTID'' -12' или что-то подобное, что я пытаюсь предотвратить. Я работаю в предположении, что пользователь базы данных попробует такую ​​штуку, и ее нужно каким-то образом обработать. Есть идеи? – Jamie4840

+0

Вы можете изменить свой существующий триггер insert, чтобы проверить NULL, тогда, когда CUSTID не указан, он получит значение auto_increment, иначе оно не может быть 0 или меньше. – JRD

2

Вставка ' 0 'в столбец с автоматическим приращением приводит к тому, что он увеличивает s вставляет NULL, так что вам действительно не нужно и не нужен триггер INSERT. Попробуйте использовать только триггер UPDATE.

+0

Извлечение триггера вставки, конечно, избавляется от ошибки, но это своего рода поражение объекта. Я все еще могу сделать вставку 'CUSTID'' -12' или что-то подобное, что я пытаюсь предотвратить. Я работаю в предположении, что пользователь базы данных попробует такую ​​штуку, и ее нужно каким-то образом обработать. Есть идеи? – Jamie4840

+0

Добавьте декларативное ограничение 'CHECK (custid> = 0)'. –

+0

Я не верю, что MySQL поддерживает использование 'CHECK' и не имеет альтернативы :( – Jamie4840