1

Тема: триггер не срабатывает при импорте csv

Триггер не срабатывает при импорте csv

Есть таблица с триггером. Таблица эта пустая. Импортирую csv-файл в эту таблицу, триггер не срабатывает. Когда вручную вставляю запись в эту таблицу, триггер срабатывает.

В чем подвох?

2

Re: триггер не срабатывает при импорте csv

aliputin
тригер в версии 5.0 от root начиная сверсии 5.1 от пользователя проверти версии и права...

3

Re: триггер не срабатывает при импорте csv

Всё делается от имени root. Версия 5.1. При обычных вставках триггер работает. Триггер не срабатывает только при импорте csv-файла. Именно это и есть моя проблема.

4

Re: триггер не срабатывает при импорте csv

aliputin
Приведите пример для воспроизведения проблемы.

1) Как осуществляется импорт CSV?
2) Как осуществляются обычные вставки?
3) Как выглядит триггер?

5

Re: триггер не срабатывает при импорте csv

1. Импорт осуществляется с помощью phpmyadmin через вкладку Импорт. Импортируется без проблем. Триггер не срабатывает.

2. Обычная вставка - это вручную, через вкладку Вставить. Триггер при этом работает.

3. Вот код триггера:
CREATE TRIGGER `tovar_bi` BEFORE INSERT ON `tovar`
FOR EACH ROW begin
select
sname into @fl
from groupsbrands
where groupsbrands.gid = new.gid;

if @fl is null then
insert into groupsbrands
(gid, sname)
values (new.gid, new.sname);
end if;
end

Суть триггера: Есть таблица tovar с этим триггером. Есть другая таблица groupsbrands. Если в таблице groupsbrands нет записи, соответствующей вставляемой в таблицу tovar, то вставляем такую запись в таблицу groupsbrands.

6

Re: триггер не срабатывает при импорте csv

aliputin
В вашем триггере разобраться не смог. Вот пример, который работает без проблем, как при вставке на вкладке "Вставить", так и через "Импорт CSV".

CREATE TABLE IF NOT EXISTS `csv` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `text` tinytext NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;


CREATE TABLE IF NOT EXISTS `csv_vvv` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `text` tinytext NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 ;

DROP TRIGGER IF EXISTS `csv_trigger`;
DELIMITER //
CREATE TRIGGER `csv_trigger` BEFORE INSERT ON `csv`
 FOR EACH ROW BEGIN
    INSERT INTO `csv_vvv` SET `csv_vvv`.`text` = NEW.`text`;
end
//
DELIMITER ;

Пример CSV файла csv.csv:

1;"fdsa"
2;"vvv"

7 (изменено: aliputin, 2010-08-28 14:20:01)

Re: триггер не срабатывает при импорте csv

Hanut
Да, Ваш код работает. Спасибо.
Значит, ошибка в моем коде. Но почему тогда мой триггер срабатывает при ручной вставке? Он ведь должен работать либо всегда, либо никогда.

8

Re: триггер не срабатывает при импорте csv

aliputin
Попробуйте такой запрос, при нем будут вставлены только строки с уникальными ключами.
INSERT IGNORE INTO `csv_vvv` (`csv_vvv`.`id`, `csv_vvv`.`text`) VALUES (NEW.`id`, NEW.`text`);

9

Re: триггер не срабатывает при импорте csv

Я добавил в код своего триггера одну строку и он заработал. Проблема в том, что я не понимаю, почему он заработал.

Вот код (добавил первую строку):

CREATE TRIGGER `tovar_bi` BEFORE INSERT ON `tovar`
FOR EACH ROW begin

set @fl = null; #это добавленная строка

select
sname into @fl
from groupsbrands
where groupsbrands.gid = new.gid;

if @fl is null then
insert into groupsbrands
(gid, sname)
values (new.gid, new.sname);
end if;
end

Почему этот код не работал без этой строки и почему работает теперь?

10

Re: триггер не срабатывает при импорте csv

aliputin
Строка означает объявление пользовательской переменной.
[mono]set @fl = null;[/mono]

Скорее странно почему раньше работало. Хотя и сейчас код не идеален.

Но я не могу разобраться в вашем триггере без структуры таблиц и без примера данных.

11

Re: триггер не срабатывает при импорте csv

Суть моего триггера понять нетрудно, если сравнить с Вашим. В Вашем триггере осуществляется безусловная вставка, в моем - условная. Если в таблице 2 уже есть аналогичная запись, тогда нет вставки. Если такой записи нет, тогда вставляем.

Чтобы узнать, есть ли такая запись, делается выборка из таблицы 2 в переменную @fl. Если эта переменная содержит что-нибудь, значит такая запись уже есть. Если же переменная равна null, тогда записи еще нет, и делается вставка.

12

Re: триггер не срабатывает при импорте csv

aliputin
Если у вас есть поле первичного ключа и это поле содержит уникальные значения, то попробуйте запрос вида:

REPLACE INTO `csv_vvv` (`csv_vvv`.`id`, `csv_vvv`.`text`) VALUES (NEW.`id`, NEW.`text`);

Думаю это оптимальный вариант. Но проверка уникальности проходит по первичному ключу, а не по значению.

В вашем случае код триггера будет такой:

DROP TRIGGER IF EXISTS `tovar_bi`;
DELIMITER //
CREATE TRIGGER `tovar_bi` BEFORE INSERT ON `tovar`
  FOR EACH ROW BEGIN
    REPLACE INTO `groupsbrands` (`groupsbrands`.`gid`, `groupsbrands`.`sname`) VALUES (NEW.`gid`, NEW.`sname`);
end
//
DELIMITER ;

13

Re: триггер не срабатывает при импорте csv

Если бы у меня были первичные ключи!
По причинам бизнес-логики я не могу использовать первичные ключи. Поэтому код моего триггера отличается от Вашего.

14

Re: триггер не срабатывает при импорте csv

aliputin
Давайте разбирать по пунктам.

-- Объявили пользовательскую переменную @fl.
set @fl = null;

-- Здесь в переменную @fl попадает значение из поля sname выбираемое по gid. Поле gid - это первичный ключ?
-- Обратите внимание, что если значение запроса не найдено, то в переменной @fl будет 0 байт в бинарном виде (ноль байт - это не null! Это важно!).
select
sname into @fl
from groupsbrands
where groupsbrands.gid = new.gid;

-- Если в переменной @fl находится null значение (null - это не ноль байт), то выполняем вставку строки.
if @fl is null then
insert into groupsbrands
(gid, sname)
values (new.gid, new.sname);
end if;

Я не вижу смысла в такой конструкции, поэтому предложил REPLACE, ведь вы все-равно используете поле gid для выборки значения поля sname в первом запросе SELECT.

15

Re: триггер не срабатывает при импорте csv

Поле gid - уникальное (UNIQUE), но не объявлено как первичный ключ.

>>ноль байт - это не null! Это важно!

Я думал, что если условие первой выборки не удовлетворено, то значение переменной @fl не изменяется. Выходит, по-Вашему, в этой переменной теперь будет ноль байт? Но как тогда второй запрос запускается? Ведь там задано условие is null?

16

Re: триггер не срабатывает при импорте csv

Допустим, в импорте две записи. Первая запись уже есть в таблице groupsbrands, вторая запись новая.

По-шагово.

Триггер запускается для первой записи.
@fl = null
sname = 'DVD'
@fl = 'DVD'
т.к. @fl <> null, второй запрос не выполняется.

Триггер запускается для второй записи.
@fl = null
sname = не понятно что (ноль байт)
@fl = ноль байт (по-Вашему) или текущее значение, т.е. null (по-моему)
т.к. @fl <> null, второй запрос не выполняется (по-Вашему)
или @fl = null, второй запрос выполняется (по-моему).

Тут я не понимаю. Если правы Вы (ноль байт - это не null), тогда мой триггер не должен выполнить второй запрос на вставку. Но он выполняется. Значит, прав я (значение переменной @fl не изменяется).

17

Re: триггер не срабатывает при импорте csv

aliputin
Посмотрите что в переменной @fl записав ее содержимое в текстовое поле.

if @fl is null then
insert into groupsbrands
(gid, sname)
values (new.gid, @fl);

Уникальное поле (UNIQUE) тоже будет работать в REPLACE запросе.

18

Re: триггер не срабатывает при импорте csv

Hanut
В данном случае, т.к. условие сработало, то в текстовом поле будет null.

19

Re: триггер не срабатывает при импорте csv

aliputin
Значит бинарный ноль байт транслируется в null значение.

Я пока не вижу преимущества использования переменной @fl вместо REPLACE запроса.

20

Re: триггер не срабатывает при импорте csv

Hanut
Спасибо за разбор ситуации.