【发布时间】:2020-03-22 20:20:43
【问题描述】:
假设您有两张桌子。
数据由外部进程填充到其中一个表中(此处称为“事件”),并通过调用存储过程进行处理,该存储过程采用一些参数并尝试在其中查找记录表“事件”。如果找到它,它会在第二个表“action”中创建一条记录,并在“event”中标记匹配的记录,以防止在程序再次运行时再次处理它们。
在正常情况下,我会在表“事件”上使用“更新游标”,并将该字段设置为在游标循环中处理。但似乎 MySQL 不支持这一点。所以我寻找了另一种方法。我只是将表“事件”的匹配记录的 ID 存储在临时表中,然后尝试使用存储在临时表中的 ID 的约束来更新表“事件”。
该过程将由一个 shell 脚本调用,该脚本将一个变量设置为今天的日期并将其传递给该过程。 我期望的是只有临时表中带有 ID 的表“事件”的记录被更新。但是发生的情况是:表“event”的所有记录,字段为 event.submitted of today。
有人能解释一下吗?我找不到我的谬误...
您可以自己检查行为。
这会生成表格(更改数据库名称以匹配您的):
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
非常感谢!
【问题讨论】: