SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 11.04.2015 20:08:09

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Помогите, плз, с триггером.

Здравствуйте.

Есть вот такой триггер:

drop trigger if exists `synk_qt`
delimiter $$
CREATE TRIGGER `sync_qt` AFTER UPDATE ON `a_table`
FOR EACH ROW
BEGIN
UPDATE `b_table` SET `p_q` = `a_table.p_q`;
END $$
delimiter;

При его наличие нельзя сделать апдейт записи - выдает ошибку #1054 - Unknown column 'a_table.p_q' in 'field list'. А он должен срабатывать как раз после такого апдейта.

Подскажите, пожалуйста, где ошибка. Я в SQL ноль, мои познания закончились 20 лет назад на DBase 4 smile

Заранее благодарю.

Неактивен

 

#2 11.04.2015 20:34:47

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Помогите, плз, с триггером.

Доброго дня.

`a_table.p_q`
попробуйте заменить на
`a_table`.`p_q`


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#3 11.04.2015 20:39:21

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

На самом деле, оно так и написано, я упрощал здесь названия таблиц и полей и промахнулся.

Неактивен

 

#4 11.04.2015 20:44:16

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Помогите, плз, с триггером.

А Вы не упрощайте, приведие ровно так, как есть. и структуру таблички не забудьте приложить ( show create table `t` )


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 11.04.2015 20:57:04

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

ОК, триггер:
drop trigger if exists `synk_qt`
delimiter $$
CREATE TRIGGER `sync_qt` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
BEGIN
   UPDATE amr_jshopping_products SET product_quantity = art_jshopping_products.product_quantity;
END $$
delimiter;

таблица:
   
Field    Type    Null    Key    Default    Extra
product_id    int(11)    NO    PRI    NULL    auto_increment
parent_id    int(11)    NO    MUL    NULL   
product_ean    varchar(32)    NO    MUL    NULL   
product_quantity    decimal(12,2)    NO        NULL   
unlimited    tinyint(1)    NO    MUL    NULL   
product_availability    varchar(1)    NO        NULL   
product_date_added    datetime    NO        0000-00-00 00:00:00   
date_modify    datetime    NO        0000-00-00 00:00:00   
product_publish    tinyint(1)    NO    MUL    NULL   
product_tax_id    tinyint(3)    NO    MUL    NULL   
currency_id    int(4)    NO    MUL    NULL   
product_template    varchar(64)    NO        default   
product_url    varchar(255)    NO        NULL   
product_old_price    decimal(14,4)    NO        NULL   
product_buy_price    decimal(14,4)    NO        NULL   
product_price    decimal(18,6)    NO    MUL    NULL   
min_price    decimal(12,2)    NO    MUL    NULL   
different_prices    tinyint(1)    NO        NULL   
product_weight    decimal(14,4)    NO        NULL   
product_thumb_image    varchar(255)    NO        NULL   
product_name_image    varchar(255)    NO        NULL   
product_full_image    varchar(255)    NO        NULL   
product_manufacturer_id    int(11)    NO    MUL    NULL   
product_is_add_price    tinyint(1)    NO        NULL   
add_price_unit_id    int(3)    NO    MUL    NULL   
average_rating    float(4,2)    NO    MUL    NULL   
reviews_count    int(11)    NO    MUL    NULL   
delivery_times_id    int(4)    NO    MUL    NULL   
hits    int(11)    NO    MUL    NULL   
weight_volume_units    decimal(14,4)    NO        NULL   
basic_price_unit_id    int(3)    NO    MUL    NULL   
label_id    int(11)    NO    MUL    NULL   
vendor_id    int(11)    NO    MUL    NULL   
access    int(3)    NO    MUL    1   
name_en-GB    varchar(255)    NO        NULL   
alias_en-GB    varchar(255)    NO        NULL   
short_description_en-GB    text    NO        NULL   
description_en-GB    text    NO        NULL   
meta_title_en-GB    varchar(255)    NO        NULL   
meta_description_en-GB    text    NO        NULL   
meta_keyword_en-GB    text    NO        NULL   
name_ru-RU    varchar(255)    NO        NULL   
alias_ru-RU    varchar(255)    NO        NULL   
short_description_ru-RU    text    NO        NULL   
description_ru-RU    text    NO        NULL   
meta_title_ru-RU    varchar(255)    NO        NULL   
meta_description_ru-RU    text    NO        NULL   
meta_keyword_ru-RU    text    NO        NULL

Неактивен

 

#6 12.04.2015 11:07:41

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Помогите, плз, с триггером.

Не очень пойму смысл триггера Вашего - Вы же ничего не делаете с полем product_quantity.

А вообще NEW нужно указывать
UPDATE amr_jshopping_products SET NEW.product_quantity = art_jshopping_products.product_quantity;
( см. http://dev.mysql.com/doc/refman/5.6/en/ … yntax.html )


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#7 12.04.2015 14:50:55

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Без продвинутого ХШ не понять, но если мой не врет, то подразумевалось что-то вроде:

MariaDB [test]> create table t1 (id int);
Query OK, 0 rows affected (0.22 sec)

MariaDB [test]> create table t2 (id int);
Query OK, 0 rows affected (0.16 sec)

MariaDB [test]> insert into t1 values(1),(2);
Query OK, 2 rows affected (0.22 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [test]> insert into t2 values(1),(2);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [test]> delimiter $$
MariaDB [test]> create trigger `t1_au` after update on t1
    -> for each row
    -> begin
    -> update t2 set id = t1.id;
    -> end $$
Query OK, 0 rows affected (0.53 sec)

MariaDB [test]> delimiter ;
MariaDB [test]> update t1 set id=3 where id=2;
ERROR 1054 (42S22): Unknown column 't1.id' in 'field list'
MariaDB [test]> drop trigger t1_au;
Query OK, 0 rows affected (0.00 sec)

MariaDB [test]> delimiter $$
MariaDB [test]> create trigger `t1_au` after update on t1
    -> for each row
    -> begin
    -> update t2 set id = new.id;
    -> end $$
Query OK, 0 rows affected (0.42 sec)

MariaDB [test]> delimiter ;
MariaDB [test]> select * from t1;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

MariaDB [test]> select * from t2;
+------+
| id   |
+------+
|    1 |
|    2 |
+------+
2 rows in set (0.00 sec)

MariaDB [test]> update t1 set id=3 where id=2;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [test]> select * from t2;
+------+
| id   |
+------+
|    3 |
|    3 |
+------+
2 rows in set (0.00 sec)

MariaDB [test]> select * from t1;
+------+
| id   |
+------+
|    1 |
|    3 |
+------+
2 rows in set (0.00 sec)
 

Неактивен

 

#8 12.04.2015 15:53:39

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

deadka написал:

Не очень пойму смысл триггера Вашего - Вы же ничего не делаете с полем product_quantity.

А вообще NEW нужно указывать
UPDATE amr_jshopping_products SET NEW.product_quantity = art_jshopping_products.product_quantity;
( см. http://dev.mysql.com/doc/refman/5.6/en/ … yntax.html )

Да, про NEW я уже понял.

Опишу проблему:

есь три и-магазина на джумле. Движки одинаковые, БД общая, таблицы - разные, id товаров одинаковые, цены и описания разные.

Я пытаюсь с помощью триггеров на апдейт синхронизировать остатки всех трех магазинов (склад у них общий).

Идея в том, чтобы на каждую таблицу товара повесить триггер, который при изменении остатка товара будет изменять остаток в 2х других таблицах. Но так получается замкнутый круг. Разорвать его мне кажется можно проверкой if - then - если разницы между новым и старым значением нет, то и апдейт выполнять не нужно. Но что-то я делаю не так, но не понимаю что.

Триггер сейчас вот такой:

DROP TRIGGER IF EXISTS `sync_qt_art`;

CREATE TRIGGER `sync_qt_art` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
BEGIN
IF OLD.`product_quantity` > NEW.`product_quantity` THEN
UPDATE `amr_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;
END IF;
END;

Без if - then он работает пока я его не повесил на все три таблицы. Когда повесил на все три БД стала ругаться. Правда триггер с if - then тоже не работает.

Неактивен

 

#9 12.04.2015 16:13:23

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Что значит "ругаться"?

Есть ощущение, что вы вообще пошли не тем путем, и вам нужно просто сделать update.
Приведите тестовый набор данных на трех таблицах и какой результат вы хотите получить.

Неактивен

 

#10 12.04.2015 16:56:04

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

vasya написал:

Что значит "ругаться"?

Есть ощущение, что вы вообще пошли не тем путем, и вам нужно просто сделать update.
Приведите тестовый набор данных на трех таблицах и какой результат вы хотите получить.

Приведу 2 таблицы с полями, которые участвуют в транзакциях (третья - аналогичная):
art_jshopping_products

+-------------+-------------------+
| product_id  | product_quantity |
|                 |                        |
+-------------+-------------------+
|    1            |         3             |
|    2            |         5             |
+-------------+-------------------+

amr_jshopping_products

+-------------+-------------------+
| product_id  | product_quantity |
|                 |                        |
+-------------+-------------------+
|    1            |         3             |
|    2            |         5             |
+-------------+-------------------+

Движок 1го магазина изменяет art_jshopping_products.product_quantity с product_id = 2 c 5 на 3, триггер после этого изменения изменяет значение 2ой таблицы amr_jshopping_products.product_quantity с product_id = 2 c 5 на 3. Во второй таблице есть такой же триггер, но с другими префиксами таблиц, который делает эту же операцию с третьей таблицей, а та в свою очередь меняет первую. Это делается для того, чтобы триггеры были максимально простыми (с одним условием). Если продажа произойдет во втором или третьем магазине, их триггеры сработают так же и product_quantity изменится во всех трех таблицах. Но в такой ситуации должно быть условие, по которому этот цикл останавливается (т.е. когда значение product_quantity в двух таблицах одинаковое).

Вот этот триггер делает просто апдейт. Но если из три и действие одного приводит к срабатыванию следующего (и так по кругу), то джумла ругается "Ошибка записи в базу данных", а phpmyadmin говорит, что таблица уже занята триггером smile

DROP TRIGGER IF EXISTS `sync_qt_art`;

CREATE TRIGGER `sync_qt_art` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
UPDATE `amr_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;

Отредактированно pawana (12.04.2015 17:08:17)

Неактивен

 

#11 12.04.2015 17:02:53

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

А для чего делать триггер с одним условием?
Логично, если при изменении первой таблице триггер обновит значения во второй и третьей,  а так вы на ровном месте создаете цикличность, которую потом пытаетесь героически преодолеть.

Неактивен

 

#12 12.04.2015 17:26:04

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

vasya написал:

А для чего делать триггер с одним условием?
Логично, если при изменении первой таблице триггер обновит значения во второй и третьей,  а так вы на ровном месте создаете цикличность, которую потом пытаетесь героически преодолеть.

Ну да, тут Вы правы на все 100.

Но, даже если переделываю триггер, то он все равно вызовет срабатывание аналогичных триггеров в 2х других таблицах. Все равно цикл выходит. И его все равно нужно остановить.

Я повесил вот такой триггер на 3 таблицы (ессно, названия триггера и префиксы разные)

DROP TRIGGER IF EXISTS `sync_qt_tls`;

CREATE TRIGGER `sync_qt_tls` AFTER UPDATE ON `tls_jshopping_products`
FOR EACH ROW
UPDATE `art_jshopping_products`, `amr_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;

Выдает такую ошибку: Column 'product_quantity' in field list is ambiguous. Цикл все равно срабатывает.

Неактивен

 

#13 12.04.2015 17:39:36

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Если вы хотите обновить значение `product_quantity` в таблицах `art_jshopping_products`, `amr_jshopping_products`, то сделайте 2 update

Неактивен

 

#14 12.04.2015 18:00:42

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Ага, понял. Вот пример для двух таблиц.


CREATE TABLE `t1` (`id` int, `q` int);
CREATE TABLE `t2` (`id` int, `q` int);

insert into t1 values(1,3),(2,5);
insert into t2 values(1,3),(2,5);

delimiter $$
CREATE TRIGGER `t1_au` AFTER UPDATE ON `t1`
FOR EACH ROW
begin
select t2.q into @a from t2 where id = new.id;
if new.q <> @a then
UPDATE `t2` SET `q` = NEW.`q` WHERE `id` = new.`id`;
end if;
end $$

CREATE TRIGGER `t2_au` AFTER UPDATE ON `t2`
FOR EACH ROW
begin
select t1.q into @a from t1 where id = new.id;
if new.q <> @a then
UPDATE `t1` SET `q` = NEW.`q` WHERE `id` = new.`id`;
end if;
end $$

update t1 set q=3 where id=2;

MariaDB [test]> select * from t1;
+------+------+
| id   | q    |
+------+------+
|    1 |    3 |
|    2 |    3 |
+------+------+
2 rows in set (0.00 sec)

MariaDB [test]> select * from t2;
+------+------+
| id   | q    |
+------+------+
|    1 |    3 |
|    2 |    3 |
+------+------+
2 rows in set (0.00 sec)
 

Неактивен

 

#15 12.04.2015 18:41:53

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

Сделал вот так:

CREATE TRIGGER `synk_art` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
begin
select `amr_joomshopping_products`.`product_quantity` into @a from `amr_joomshopping_products` where `product_ean` = new.`product_ean`;
if new.`product_quantity` > @a then
UPDATE `amr_joomshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_ean` = new.`product_ean`;
end if;
end

Вылезла ошибка: ошибка #1064 (42000) - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3

Неактивен

 

#16 12.04.2015 18:53:53

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

Извините, просто phpmyadmin - зло smile

Неактивен

 

#17 12.04.2015 19:01:53

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

Переделал триггер
delimiter $$
DROP TRIGGER IF EXISTS sync_qt_art;
CREATE TRIGGER `sync_qt_art` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
begin
select amr_jshopping_products.product_quantity into @a from amr_jshopping_products where product_id = new.product_id;
if new.product_id > @a then
UPDATE `amr_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;
end if;
end $$

ошибок нет, но значение во второй таблице не изменяется

Неактивен

 

#18 12.04.2015 19:58:34

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Называется найдите 10 отличий smile
Почему у вас new.product_id > @a ?

Неактивен

 

#19 12.04.2015 19:59:19

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

Извините, не только phpmyadmin, но и нубы тоже зло smile

Vasya, Deadka, спасибо огроменное вам. Мучения многих лет похоже закончились.

Это итоговый триггер, изменяющий поле с остатком товара в 2 таблицах после апдейта в искомой.

delimiter $$
DROP TRIGGER IF EXISTS `sync_qt_art`;
CREATE TRIGGER `sync_qt_art` AFTER UPDATE ON `art_jshopping_products`
FOR EACH ROW
begin
select amr_jshopping_products.product_quantity into @art1 from amr_jshopping_products where product_id = new.product_id;
if new.product_quantity < @art1 then
UPDATE `amr_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;
end if;
select tls_jshopping_products.product_quantity into @art2 from tls_jshopping_products where product_id = new.product_id;
if new.product_quantity < @art2 then
UPDATE `tls_jshopping_products` SET `product_quantity` = NEW.`product_quantity` WHERE `product_id` = new.`product_id`;
end if;
end $$

Остальные триггеры - аналогичные с учетом изменения префиксов и имен переменных.

Жаль нет плюсиков каких-нибудь, я бы три поставил smile

Отредактированно pawana (12.04.2015 20:00:12)

Неактивен

 

#20 12.04.2015 20:06:11

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Помогите, плз, с триггером.

Ну радоваться рано - это только начало.
Решение плохое. Изменили первую таблицу, триггер меняет данные во второй, в это время вновь изменили первую, триггер на второй лезет в первую и ошибка.
Так что как временное решение пойдет, но дальше смотреть в сторону правки кода джумлы под себя (например, чтобы сразу менять данные во всех трех таблицах).

Неактивен

 

#21 12.04.2015 20:17:12

pawana
Участник
Зарегистрирован: 11.04.2015
Сообщений: 14

Re: Помогите, плз, с триггером.

Я согласен, что решение не идеальное, но хак ядра джумлы тоже не фонтан, там боков еще больше может быть. При небольшой нагрузке на магазин при небольшом кол-ве товара это решение жизнеспособное. Возможно, есть возможность изменить триггеры, типа лока таблицы и очереди на апдейт. Но с учетом, что без вас я и это бы не сделал, то... smile

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson