Предупреждение # 1366 в phpMyAdmin INSERT даже с кодом BEFORE INSERT TRIGGER, чтобы разрешить его. Природные? - PullRequest
0 голосов
/ 17 января 2019

Резюме

Когда я использую графический интерфейс phpMyAdmin для вставки новой записи в мою таблицу (к которой применен BEFORE INSERT TRIGGER), она, кажется, вставляет эту запись просто отлично ... но она всегда отображает это в ответ:

(!) 1 строка вставлена.
Предупреждение: # 1366 Неверное целочисленное значение: '' для столбца 'line_id' в строке 1

Что я делаю не так? Есть ли лучший способ настроить триггер, чтобы я не получил ошибку?

Фон

Примечание. Скорее всего, вы можете пропустить кодовые блоки при чтении.

Используя phpMyAdmin, я создал вторую таблицу с этим оператором SQL. (Это работало нормально.)

CREATE TABLE IF NOT EXISTS `myDb`.`line_item` (
  `order_id` INT NOT NULL,
  `line_id` INT NOT NULL,
  `line_text` VARCHAR(100) NOT NULL,
  PRIMARY KEY (`order_id`, `line_id`),
  CONSTRAINT `FK_order_line_item`
    FOREIGN KEY (`order_id`)
    REFERENCES `myDb`.`order` (`order_id`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

Вы заметите, что на line_id наложено нет AUTO_INCREMENT. Это потому, что мы хотим, чтобы он сбрасывал нумерацию с каждым новым order_id . Для выполнения этого номера сброса мы предположили, что ТРИГГЕР наиболее подходит для этой задачи.

Когда я попытался добавить TRIGGER с этим кодом, phpMyAdmin сказал, что не может этого сделать. (Что-то делать с « разрешениями » или чем-то подобным, но я быстро прибегнул к встроенному обходному решению после этого небольшого приключения.)

DELIMITER $$
USE `myDb`$$
CREATE DEFINER = CURRENT_USER TRIGGER `myDb`.`line_id_incrementer` 
BEFORE INSERT ON `line_item` 
FOR EACH ROW
BEGIN
    DECLARE i INT;
    SELECT  COALESCE(MAX(line_id), 0) + 1
    INTO    i
    FROM    line_item
    WHERE   order_id = NEW.order_id;
    SET NEW.line_id = i;
END$$

DELIMITER ;

Когда вышеприведенный оператор SQL не работал, я просто использовал графический интерфейс phpMyAdmin для добавления триггера в таблицу.

Сервер: localhost > База данных: myDb > Таблица: line_item > Вкладка «Триггеры»> «Новый»> «Добавить триггер»

Имя триггера : line_id_incrementer
Таблица : line_item
Время : ДО
Событие : ВСТАВИТЬ
Определение :

BEGIN
    DECLARE i INT;
    SELECT  COALESCE(MAX(line_id), 0) + 1
    INTO    i
    FROM    line_item
    WHERE   order_id = NEW.order_id;
    SET NEW.line_id = i;
END

Пока все честно.

Выполняя пробный заезд, я вставил тестовую запись в таблицу «order» через графический интерфейс phpMyAdmin (вкладка «Insert» при просмотре таблицы «order»): Никаких проблем там нет .

Когда я вставил тестовую запись для 'line_id' через графический интерфейс phpMyAdmin, я оставил поле NOT_ULL 'line_id' пустым, чтобы посмотреть, будет ли триггер заполнять его правильно для меня. И вот тогда я получил это:

(!) 1 строка вставлена.
Предупреждение: # 1366 Неверное целочисленное значение: '' для столбца 'line_id' в строке 1

С сгенерированным кодом, показанным как:

INSERT INTO `line_item` 
    (`order_id`, `line_id`, `line_text`) 
    VALUES ('1', '', 'This is a test line for the incrementer trigger');

Что интересно Интересно : вставляет запись, как и ожидалось (с 1 в качестве line_id). Когда я вставил вторую запись, предупреждение все еще показывало , но следующая запись также была введена как ожидалось (с 2 в качестве line_id).

Итак, строки, кажется, вставлены просто отлично, но я продолжаю получать это ноющее предупреждение, которое заставляет меня подозревать, что я не сделал что-то в соответствии с "стандартами передовой практики".

Ответы [ 2 ]

0 голосов
/ 17 января 2019

Я не думаю, что ваше определение таблицы соответствует тому, чего вы хотите достичь. В частности, line_id и line_text определены как не нулевые. Проблема в том, что оператор вставки выполняет ненулевые тесты до срабатывания триггера и дает сбой (я предполагаю, что ваша вставка имеет только order_id и, возможно, line_text). Возможно, вы захотите посмотреть на установку значений по умолчанию. Например.

drop table if exists line_item;
CREATE TABLE `line_item` (
  `order_id` INT NOT NULL,
  `line_id` INT not null default 0,
  `line_text` VARCHAR(100) not null default '',
  PRIMARY KEY (`order_id`, `line_id`) #,
  #CONSTRAINT `FK_order_line_item`
  #  FOREIGN KEY (`order_id`)
  #  REFERENCES `myDb`.`order` (`order_id`)
  #  ON DELETE NO ACTION
  #  ON UPDATE NO ACTION)
  );

 drop trigger if exists t;
 delimiter $$
 create trigger t before insert on line_item 
 for each row
 BEGIN
DECLARE i INT;
    SELECT  MAX(line_id) + 1
    INTO    i
    FROM    line_item
    WHERE   order_id = NEW.order_id;
    SET NEW.line_id = COALESCE(i, 1);
END $$
delimiter $$

insert into line_item (order_id) values (1),(1);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

+----------+---------+-----------+
| order_id | line_id | line_text |
+----------+---------+-----------+
|        1 |       1 |           |
|        1 |       2 |           |
+----------+---------+-----------+
2 rows in set (0.00 sec)

Я не использую phpmyadmin и понятия не имею, почему он показывает предупреждение, но я предлагаю вам запустить вставку из командной строки sql, чтобы увидеть, какую ошибку она выдает.

0 голосов
/ 17 января 2019

Проблема с вашим триггером в том, что запрос SELECT ничего не вернет, если в таблице еще нет строк для текущего заказа.Одним из решений является перемещение COALESCE в SET:

BEGIN
DECLARE i INT;
    SELECT  MAX(line_id) + 1
    INTO    i
    FROM    line_item
    WHERE   order_id = NEW.order_id;
    SET NEW.line_id = COALESCE(i, 1);
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...