представьте, у вас есть две таблицы.
Данные заполняются внешним процессом в одну из таблиц (здесь называемых " event ") и обрабатываются вызовом хранимой процедуры, которая принимает некоторые параметры и пытается найти записи в таблице "событие". Если он находит его, он создает запись во второй таблице « action » и помечает совпадающие записи в «event», чтобы предотвратить их повторную обработку в случае повторного запуска процедуры.
При нормальных обстоятельствах я использовал бы «курсор для обновления» в таблице «событие» и установил поле для обработки в l oop курсора. Но, похоже, MySQL не поддерживает это. Поэтому я искал альтернативный путь. Я просто храню идентификаторы совпадающих записей таблицы «событие» во временной таблице, а позже пытаюсь обновить таблицу «событие» с ограничением на идентификаторы, хранящиеся во временной таблице.
Процедура должна быть вызывается сценарием оболочки, который устанавливает переменную на сегодняшнюю дату и передает ее в процедуру. Я ожидаю, что обновляются только записи таблицы «событие» с идентификаторами из временной таблицы. Но происходит следующее: обновляются все записи таблицы «событие» с полем «событие», представленное сегодня.
Кто-нибудь может попытаться объяснить это? Я не могу найти свою ошибку ...
Вы можете сами проверить поведение.
Это создает таблицы (измените имя базы данных, чтобы соответствовать вашему):
use yourdatabasename;
drop table if exists event;
create table if not exists event
(
id integer not null AUTO_INCREMENT,
sender varchar(127) not null,
name varchar(127) not null,
submitted Timestamp DEFAULT CURRENT_TIMESTAMP,
status varchar(127) not null,
logged Timestamp DEFAULT CURRENT_TIMESTAMP,
ub_status varchar(127) not null,
ub_status_date Timestamp DEFAULT CURRENT_TIMESTAMP,
primary key (id)
);
-- create some entries in "event" with decending timestamps
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name1', now(), 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name2', now() - interval 1 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name3', now() - interval 2 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name4', now() - interval 3 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name5', now() - interval 4 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name6', now() - interval 5 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name7', now() - interval 6 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name8', now() - interval 7 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
insert into event (sender, name, submitted, status, logged,ub_status) values ('192.168.0.2', 'name9', now() - interval 8 hour, 'COMPLETED_SUCCESS',now(),'CREATED') ;
drop table if exists action;
create table if not exists action
(
id integer not null AUTO_INCREMENT,
name varchar(127) not null,
sender varchar(127) not null,
logged Timestamp not null DEFAULT CURRENT_TIMESTAMP,
status varchar(127) not null,
status_date Timestamp DEFAULT CURRENT_TIMESTAMP,
primary key (id)
);
Это является хранимой процедурой:
CREATE DEFINER=`flo_db`@`localhost` PROCEDURE `TestUpdateActionTwoJobs`(IN process_name varchar(40),
IN sendingMachine varchar(127),
IN jobname1 varchar(127),
IN jobname2 varchar(127),
IN startdate varchar(10),
IN update_event_table int)
begin
DECLARE found_count long;
DECLARE exit handler for sqlexception
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
SET @full_error = CONCAT("ERROR ", @errno, " (", @sqlstate, "): ", @text);
SELECT @full_error;
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE,
@errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
SET @full_error = CONCAT("ERROR ", @errno, " (", @sqlstate, "): ", @text);
SELECT @full_error;
ROLLBACK;
END;
/* The procedure searches for certain records in table "event" - some fields have to match, some come
* from stored procedure parameters.
* If there is a match a new record is to be created in table "action" and the found records
* in table "event" are to marked as "processed" by setting the column "event.ub_status" to "PROCESSED"
*/
SET @found_count = 0;
SET @found_tmp = 0;
START TRANSACTION;
select count(*) from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED' into @found_count ;
/* we expect exactly 2 */
IF @found_count = 2 THEN
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_UpdateActionTwoJobs
select id from event where
sender = sendingMachine
and status = 'COMPLETED_SUCCESS'
and submitted > startdate
and (name = jobname1 or name = jobname2)
and ub_status = 'CREATED';
INSERT INTO action (name, sender, logged, status, status_date) VALUES (process_name, sendingMachine,
NOW(), 'CREATED', NOW());
/* count the number of records in the temporary table */
select count(*) from tmp_UpdateActionTwoJobs into @found_tmp;
SET @info = CONCAT("number of records in tmp-table: ", @found_tmp);
/* mark the records as processed if wanted */
IF update_event_table = 1 THEN
UPDATE event SET ub_status = 'PROCESSED', ub_status_date = NOW() WHERE id in (select id tmp_UpdateActionTwoJobs );
END IF;
else
set @info = "no condition met!";
END IF;
COMMIT;
/* generate info output */
SELECT @info;
end
Чтобы вызвать процедуру, вы можете использовать такой скрипт bash (пользователь, пароль, хост и имя базы данных должны быть заменены ...):
#!/bin/bash
# we are looking for entries in "event" that were created today
today=$(date '+%Y-%m-%d')
mysql -u database_user -p'password' -h host -e "call TestUpdateActionTwoJobs('TargetJobname', '192.168.0.2', 'name2', 'name3', '$today', 1);" database_name
Большое спасибо!