Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Проверка записи на существование в триггере / 22 сообщений из 22, страница 1 из 1
19.08.2014, 13:33:46
    #38723442
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
в тригере пытаюсь проверить, существует ли уже запись в таблице.
триггер AFTER INSERT


Код: sql
1.
2.
DECLARE cnt int(10) DEFAULT 0;
SELECT count(*) INTO @cnt FROM news WHERE MsgID = @MsgID;



переменная @cnt всегда 0.
записи в таблице присутствуют
...
Рейтинг: 0 / 0
19.08.2014, 13:40:56
    #38723448
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
1) Переменные cnt и @cnt - это разные переменные.
2) А что и откуда в этот момент в переменной @MsgID?
...
Рейтинг: 0 / 0
19.08.2014, 14:01:56
    #38723471
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
1. уяснил.

будет ли правильно вот так:
Код: sql
1.
2.
DECLARE @cnt int(10) DEFAULT 0;
SELECT count(*) INTO @cnt FROM news WHERE MsgID = @MsgID;




переменная @MsgID извлекается ранее

Код: sql
1.
set @MsgID := ExtractValue(NEW.xmlData,'//Ident');



это идентификатор новости. он уникальный.
...
Рейтинг: 0 / 0
19.08.2014, 14:02:50
    #38723473
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinnyв тригере пытаюсь проверить, существует ли уже запись в таблице.
триггер AFTER INSERT


Код: sql
1.
2.
DECLARE cnt int(10) DEFAULT 0;
SELECT count(*) INTO @cnt FROM news WHERE MsgID = @MsgID;



переменная @cnt всегда 0.
записи в таблице присутствуют

интересный текст тригера... вроде как NEW.msgid

select ....;
row_count() - число найденых записей при последнем селектеж
...
Рейтинг: 0 / 0
19.08.2014, 14:05:59
    #38723477
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
alex564657498765453,

ошибочка вышла
FOUND_ROWS()
...
Рейтинг: 0 / 0
19.08.2014, 14:42:03
    #38723523
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
попробовал как указали раннее:

Код: sql
1.
2.
SELECT * FROM news WHERE MsgID = @MsgID;
SELECT FOUND_ROWS() INTO @cnt;



при обновлении тригера выдает ошибку
Not allowed to return a result set from a trigger
...
Рейтинг: 0 / 0
19.08.2014, 14:47:36
    #38723528
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinny,

Прежде, чем метаться по разным вариантам синтаксиса, опишите толком задачу.
...
Рейтинг: 0 / 0
19.08.2014, 15:50:50
    #38723602
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinnyпопробовал как указали раннее:

Код: sql
1.
2.
SELECT * FROM news WHERE MsgID = @MsgID;
SELECT FOUND_ROWS() INTO @cnt;



при обновлении тригера выдает ошибку
Not allowed to return a result set from a trigger

круто...я не сталкивался с таким ограничением на тригере, что нельзя селект делать...тогда только как ты - селект инту вар
...
Рейтинг: 0 / 0
19.08.2014, 16:30:35
    #38723645
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
miksoft,

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

ниже более подробное описание.

из внешней системы в таблицу синхронизации (replicate_table) приезжают данные в формате xml.

Код: sql
1.
insert into replicate_table (xmlData) Values ('<Root><Type>Message</Type><Action>delete</Action><Ident>55363</Ident><Deleted>0</Deleted><Mm_Sender_Id>782</Mm_Sender_Id><Mm_Sender_Name>mobus</Mm_Sender_Name><Mm_Date>2014-08-18T16:08:02</Mm_Date><Mm_Subject>1116</Mm_Subject><Msg_Text>1116</Msg_Text><Mm_Importance>N</Mm_Importance></Root>');



В этом xml содержится информация о том, что необходимо сделать, какие данные вставить/обновить/удалить.

на эту таблицу (replicate_table) навешен триггер AFTER INSERT
который и разбирает данные.

одно из условий внутри триггера, проверить, существует ли уже запись в системе по переданному идентификатору (<Ident>55363</Ident>). Идентификатор является внешним, и только по нему невозможно полностью удалить сообщение из системы, тк информация о сообщении хранится в нескольких таблицах, под внутренним идентификтором ElementID, который отличается от <Ident></Ident>


в данном случае, в xml содержится информация о удалении сообщения.

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


Обработка тега <Action> убрана, тк insert и update практически идентичны.

вообщем то загвоздка в проверке существования записей в системе, поскольку селект возвращает всегда 0
...
Рейтинг: 0 / 0
19.08.2014, 16:34:30
    #38723648
alex564657498765453
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinnymiksoft,

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

ниже более подробное описание.

из внешней системы в таблицу синхронизации (replicate_table) приезжают данные в формате xml.

Код: sql
1.
insert into replicate_table (xmlData) Values ('<Root><Type>Message</Type><Action>delete</Action><Ident>55363</Ident><Deleted>0</Deleted><Mm_Sender_Id>782</Mm_Sender_Id><Mm_Sender_Name>mobus</Mm_Sender_Name><Mm_Date>2014-08-18T16:08:02</Mm_Date><Mm_Subject>1116</Mm_Subject><Msg_Text>1116</Msg_Text><Mm_Importance>N</Mm_Importance></Root>');



В этом xml содержится информация о том, что необходимо сделать, какие данные вставить/обновить/удалить.

на эту таблицу (replicate_table) навешен триггер AFTER INSERT
который и разбирает данные.

одно из условий внутри триггера, проверить, существует ли уже запись в системе по переданному идентификатору (<Ident>55363</Ident>). Идентификатор является внешним, и только по нему невозможно полностью удалить сообщение из системы, тк информация о сообщении хранится в нескольких таблицах, под внутренним идентификтором ElementID, который отличается от <Ident></Ident>


в данном случае, в xml содержится информация о удалении сообщения.

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


Обработка тега <Action> убрана, тк insert и update практически идентичны.

вообщем то загвоздка в проверке существования записей в системе, поскольку селект возвращает всегда 0

нащот того что селект ноль вернул, тебе написали var и @var Это вде разные переменные

ту что в дикларе описал, не надо с собакой пользовать.

а ваще архитектура вцелом странная. я так полагаю это то, что скрываеться за понтовым словом рест.

приходит запрос на удаление записи 123, тебе какая разница есть она или нету - ты бери удаляй. пришла запись на вставку бери вставляй, апдейт апдейть.

или ты думаешь твой код поиска записи и анализа результата быстрее отработает чем родной скомпиленый мускла?
...
Рейтинг: 0 / 0
19.08.2014, 16:49:16
    #38723664
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
alex564657498765453,

видимо переделаю алгоритм триггера.

поскольку на один хмл инструкции вставки, необходимо добавлять по одной записи в три разных таблицы, и только две из них содержат внешний ключ MsgID, который берется из <Ident>, а третью таблицу не могу денормализовать, поскольку она системная, и это изменение архитектуры, то буду менять логику самого тригера.
...
Рейтинг: 0 / 0
19.08.2014, 16:53:30
    #38723667
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinny , у Вас совершенно кривой подход. И весьма чреватый, надо сказать - размахать с ним данные в лапшу раз плюнуть...

Напишите хранимую процедуру, которая примет эту XML-строку, распарсит её, выполнить необходимые проверки, и по их итогам аккуратно сделает ровно то, что нужно.
...
Рейтинг: 0 / 0
19.08.2014, 17:06:42
    #38723675
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akina,

эм. хорошо, помогите пожалуйста тогда исправить ошибки.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
BEGIN
DECLARE randName varchar(20);
DECLARE ShortName varchar(50);
DECLARE ElementPath varchar(100);
DECLARE ElementScript varchar(100);
DECLARE ElementName varchar(250);
DECLARE lastID varchar(10);
DECLARE ParentID varchar(10);
DECLARE is_virtual varchar(2);
DECLARE ItemID varchar(10);
DECLARE ItemName varchar(30);
DECLARE TypeItem varchar(50);
DECLARE SQLAction varchar(50);
SET @lastID := 0;
SET @TypeItem := ExtractValue(NEW.xmlData,'//Type');
SET @randName := ROUND(RAND()*(10000-1000)+1000,0);
set @ShortName :=  CONCAT(DATE_FORMAT(NOW(),'%Y%m%d%H%i%s'),'-',@randName);
CASE @TypeItem
	WHEN 'message'
	THEN
		BEGIN
			DECLARE MsgID varchar(20);
			DECLARE isDeleted int(2);
			set @MsgID := ExtractValue(NEW.xmlData,'//Ident');
			set @SQLAction := ExtractValue(NEW.xmlData,'//Action');
			
			set @ElementPath := CONCAT('/news/',@ShortName,'.html');
			set @ItemID := '12';
			set @is_virtual := '2';
			set @ParentID := '38';
			set @ItemName := 'wr_item_news';
			set @ElementScript := 'news/item';
			SET @ElementName := ExtractValue(NEW.xmlData,'//Mm_Subject');
			SET @isDeleted := ExtractValue(NEW.xmlData,'//Deleted');
			
		
			SELECT Count(MsgID) INTO @MsgCount FROM wr_item_news WHERE MsgID = @MsgID;
			IF(@MsgCount = 0)
			THEN
				INSERT INTO wr_main (
					ParentID,
					ElementName, 
					ItemID, 
					ItemName,
					isNode, 
					ElementOrder, 
					ElementPath, 
					ElementScript, 
					ShortName, 
					is_virtual, 
					HostName) 
		
				VALUES( 
					@ParentID, 
					@ElementName, 
					@ItemID,  
					@ItemName, 
					'2', 
					'0',  
					@ElementPath, 
					@ElementScript, 
					@ShortName, 
					@is_virtual,
					'*'
				);

				SET @lastID := LAST_INSERT_ID();
				INSERT INTO wr_item_news (
					ElementID,
					ParentID,
					ElementName,
					created,
					modified,
					dat,
					Sender,
					descr,
					Importance,
					`hash`,
					MsgID
				) 
				VALUES( 
					@lastID,
					@ParentID,
					@ElementName,
					UNIX_TIMESTAMP(),
					UNIX_TIMESTAMP(),
					UNIX_TIMESTAMP(STR_TO_DATE(ExtractValue(NEW.xmlData,'//Mm_Date'),'%Y-%m-%dT%H:%i:%s')),
					ExtractValue(NEW.xmlData,'//Mm_Sender_Name'),
					ExtractValue(NEW.xmlData,'//Msg_Text'),
					IF (ExtractValue(NEW.xmlData,'//Mm_Importance') = 'Y' ,'1', '0' ),
					MD5(@MsgID),
					@MsgID
					) ON DUPLICATE KEY UPDATE modified=UNIX_TIMESTAMP();
			ELSE
				IF(@isDeleted = 1 OR @SQLAction = 'delete')
				THEN
					DELETE FROM wr_main WHERE ElementID = ( SELECT ElementID FROM wr_item_news WHERE MsgID = @MsgID);
					DELETE FROM wr_item_newsrecipients WHERE MsgID = @MsgID;
					DELETE FROM wr_item_news WHERE MsgID = @MsgID;
				END IF; 
			END IF;
				
		END;
	WHEN 'Message_Ref'
	THEN
		BEGIN
		
		INSERT INTO wr_item_newsrecipients (
				ParentID,
				Recipient,
				IsRead,
				MsgID
			) 
			SELECT 
				@lastID,
				ExtractValue(NEW.xmlData,'//Mf_Receiver_Name'),
				IF (ExtractValue(NEW.xmlData,'//Mf_Message_Read') = 'Y' ,'1', '0' ),
				ExtractValue(NEW.xmlData,'//Mf_Message_Id')
				;
				
		END;
	END CASE;
END
...
Рейтинг: 0 / 0
19.08.2014, 17:23:54
    #38723692
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Ошибок две.
Первая - вместо того, чтобы выбросить всё нахрен и написАть с нуля, но в форме процедуры, предпринимается попытка "исправить". Она основаная, идеологическая.

Вторая - декларируется хренова гора переменных, которые потом не используются. Она синтаксическая и, в общем, безобидная.
...
Рейтинг: 0 / 0
19.08.2014, 17:32:33
    #38723698
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akina,

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

синтаксические ошибки помогите исправить.


идея вынести основную логику в процедуру и вызывать из тригера ее, была, просто не дошел до этого момента, тк споткнулся на сабж топика.
...
Рейтинг: 0 / 0
19.08.2014, 17:39:29
    #38723707
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
nevinnyв форме процедуры или триггера - помоему не сильно важноno comments
...
Рейтинг: 0 / 0
19.08.2014, 18:11:39
    #38723755
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akinanevinnyв форме процедуры или триггера - помоему не сильно важноno comments

авторвозможно ошибаюсь, поясните.
...
Рейтинг: 0 / 0
19.08.2014, 18:35:19
    #38723775
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Поясняю.
1) Триггер жёстко привязан к записи, добавление/удаление/изменение которой вызвало срабатывание триггера. Процедура такой привязки не имеет.
2) Триггер ограничен в перечне используемых конструкций. В т.ч. и как следствие из 1-го отличия. Ограничения у процедур несколько мягче.
3) Триггер гарантированно срабатывает только на определённый и, к сожалению, не исчерпывающий, набор действий, формально выполняющий условия срабатывания. Процедура при вызове выполняется безусловно.
4) Триггер выполняется линейно (выполнение триггера для следующей запписи набора начинается только после завершения выполнения триггера для предыдущей записи) и, емнип, однозадачно (т.е. не могут одновременно выполняться два тела одного триггера, инициированные двумя разными запросами). Экземпляры процедур выполняются параллельно.
5) Триггер всегда обрабатывает только одну запись инициирующего набора. Процедура не имеет такого ограничения.

Эти отличия (и куча прочих) имеют следствием то, что подход при написании триггера и процедуры различен.
...
Рейтинг: 0 / 0
19.08.2014, 19:10:56
    #38723803
nevinny
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akina,

Спасибо за пояснения, очень помогли! )

решил свою проблему с помощью процедур.
...
Рейтинг: 0 / 0
19.08.2014, 19:13:08
    #38723804
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akinaне могут одновременно выполняться два тела одного триггера, инициированные двумя разными запросамиЭм... Это точно?
Не вижу никаких логичных причин для этого...
...
Рейтинг: 0 / 0
19.08.2014, 21:22:47
    #38723889
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
miksoftAkinaне могут одновременно выполняться два тела одного триггера, инициированные двумя разными запросамиЭм... Это точно?
Не вижу никаких логичных причин для этого...
Если это НЕ так - триггер просто обязан блокировать как минимум текущую запись на всё время своей работы. В противном случае возможна параллельная работа двух экземпляров триггера над одной и той же записью, что потенциально приведёт к нарушению целостности и/или разрушению данных. А с учётом того, что триггеру позволено изменять данные других таблиц - он должен блокировать также и их, по тем же причинам.
...
Рейтинг: 0 / 0
19.08.2014, 22:05:15
    #38723911
miksoft
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Проверка записи на существование в триггере
Akinamiksoftпропущено...
Эм... Это точно?
Не вижу никаких логичных причин для этого...
Если это НЕ так - триггер просто обязан блокировать как минимум текущую запись на всё время своей работы. Это и так происходит. В случае MyISAM блокируется вся таблица. В случае InnoDB блокируется, как минимум, изменяемая запись.
Все равно не вижу, почему один и тот же триггер не может работать одновременно над двумя разными записями в двух разных сессиях.
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Проверка записи на существование в триггере / 22 сообщений из 22, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]