MySQL 程序嵌套游标
MySQL Procedure nested cursor
我正在努力处理 MySQL 程序。所以,我有两个 tables
Table 用户
id user
--------------
1 user_1
2 user_2
3 user_3
4 user_4
Table 笔交易
id user_id transaction_type
---------------------------
1 5 cash
2 5 non cash
3 5 cash
4 5 cash
5 5 cash
现在我想更新事务 table 中的 user_id 并按顺序替换为用户 table 中的 ID。
我想要的结果是这样的
id user_id transaction_type
---------------------------
1 1 cash
2 2 non cash
3 3 cash
4 4 cash
5 1 cash
我试过像下面这样的程序,但不能正常工作,也不能按顺序更新。
CREATE DEFINER=`root`@`%` PROCEDURE `sequentially_update`()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE i int DEFAULT 500;
DECLARE userId int DEFAULT 0;
DECLARE transactionType int DEFAULT 0;
DEClARE curTransactions CURSOR FOR
SELECT * FROM transactions;
DECLARE curUsers CURSOR FOR
SELECT user_id FROM users
ORDER BY RAND() LIMIT 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN curTransactions;
loopTransactions: LOOP
FETCH curContacts INTO transactionType;
IF finished = 1 THEN
LEAVE loopTransactions;
END IF;
OPEN curUsers;
FETCH curUsers INTO userId;
CLOSE curUsers;
UPDATE transactions SET user_id = userId;
END LOOP loopTransactions;
CLOSE curTransactions;
END
在这种情况下如何在 MySQL 中创建正确的程序?
我建议使用一种稍微不同的方法,避免使用 2 个处理程序(1 个用于用户,1 个用于事务)并为用户使用偏移量和限制。注意,您只需要来自交易的 ID
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T
(id INT, user VARCHAR(10));
INSERT INTO T VALUES
(1 , 'user_1'),
(2 , 'user_2'),
(3 , 'user_3'),
(4 , 'user_4');
CREATE TABLE T1
(id INT, user_id INT, transaction_type VARCHAR(10));
INSERT INTO T1 VALUES
( 1 , 5 , 'cash'),
( 2 , 5 , 'non cash'),
( 3 , 5 , 'cash'),
( 4 , 5 , 'cash'),
( 5 , 5 , 'cash');
DROP PROCEDURE IF EXISTS P;
DELIMITER $$
CREATE PROCEDURE P()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE i int DEFAULT 500;
DECLARE userId int DEFAULT 0;
DECLARE VtransactionID int DEFAULT 0;
declare voffset int default 0;
declare vid int;
declare vmax_rows int;
DEClARE curTransactions CURSOR FOR
SELECT ID FROM t1 order by id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
select count(*) into vmax_rows from t;
select vmax_rows;
OPEN curTransactions;
loopTransactions: LOOP
FETCH curTransactions INTO Vtransactionid;
IF finished = 1 THEN
LEAVE loopTransactions;
END IF;
select voffset;
select id into vid from t order by id limit voffset,1;
set voffset = voffset + 1;
if voffset = vmax_rows then
set voffset = 0 ;
end if;
UPDATE t1 SET user_id = vid WHERE ID = vtransactionID;
END LOOP loopTransactions;
CLOSE curTransactions;
END $$
delimiter ;
call p();
select * from t1;
+------+---------+------------------+
| id | user_id | transaction_type |
+------+---------+------------------+
| 1 | 1 | cash |
| 2 | 2 | non cash |
| 3 | 3 | cash |
| 4 | 4 | cash |
| 5 | 1 | cash |
+------+---------+------------------+
5 rows in set (0.00 sec)
我正在努力处理 MySQL 程序。所以,我有两个 tables
Table 用户
id user
--------------
1 user_1
2 user_2
3 user_3
4 user_4
Table 笔交易
id user_id transaction_type
---------------------------
1 5 cash
2 5 non cash
3 5 cash
4 5 cash
5 5 cash
现在我想更新事务 table 中的 user_id 并按顺序替换为用户 table 中的 ID。
我想要的结果是这样的
id user_id transaction_type
---------------------------
1 1 cash
2 2 non cash
3 3 cash
4 4 cash
5 1 cash
我试过像下面这样的程序,但不能正常工作,也不能按顺序更新。
CREATE DEFINER=`root`@`%` PROCEDURE `sequentially_update`()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE i int DEFAULT 500;
DECLARE userId int DEFAULT 0;
DECLARE transactionType int DEFAULT 0;
DEClARE curTransactions CURSOR FOR
SELECT * FROM transactions;
DECLARE curUsers CURSOR FOR
SELECT user_id FROM users
ORDER BY RAND() LIMIT 1;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
OPEN curTransactions;
loopTransactions: LOOP
FETCH curContacts INTO transactionType;
IF finished = 1 THEN
LEAVE loopTransactions;
END IF;
OPEN curUsers;
FETCH curUsers INTO userId;
CLOSE curUsers;
UPDATE transactions SET user_id = userId;
END LOOP loopTransactions;
CLOSE curTransactions;
END
在这种情况下如何在 MySQL 中创建正确的程序?
我建议使用一种稍微不同的方法,避免使用 2 个处理程序(1 个用于用户,1 个用于事务)并为用户使用偏移量和限制。注意,您只需要来自交易的 ID
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T
(id INT, user VARCHAR(10));
INSERT INTO T VALUES
(1 , 'user_1'),
(2 , 'user_2'),
(3 , 'user_3'),
(4 , 'user_4');
CREATE TABLE T1
(id INT, user_id INT, transaction_type VARCHAR(10));
INSERT INTO T1 VALUES
( 1 , 5 , 'cash'),
( 2 , 5 , 'non cash'),
( 3 , 5 , 'cash'),
( 4 , 5 , 'cash'),
( 5 , 5 , 'cash');
DROP PROCEDURE IF EXISTS P;
DELIMITER $$
CREATE PROCEDURE P()
BEGIN
DECLARE finished INTEGER DEFAULT 0;
DECLARE i int DEFAULT 500;
DECLARE userId int DEFAULT 0;
DECLARE VtransactionID int DEFAULT 0;
declare voffset int default 0;
declare vid int;
declare vmax_rows int;
DEClARE curTransactions CURSOR FOR
SELECT ID FROM t1 order by id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1;
select count(*) into vmax_rows from t;
select vmax_rows;
OPEN curTransactions;
loopTransactions: LOOP
FETCH curTransactions INTO Vtransactionid;
IF finished = 1 THEN
LEAVE loopTransactions;
END IF;
select voffset;
select id into vid from t order by id limit voffset,1;
set voffset = voffset + 1;
if voffset = vmax_rows then
set voffset = 0 ;
end if;
UPDATE t1 SET user_id = vid WHERE ID = vtransactionID;
END LOOP loopTransactions;
CLOSE curTransactions;
END $$
delimiter ;
call p();
select * from t1;
+------+---------+------------------+
| id | user_id | transaction_type |
+------+---------+------------------+
| 1 | 1 | cash |
| 2 | 2 | non cash |
| 3 | 3 | cash |
| 4 | 4 | cash |
| 5 | 1 | cash |
+------+---------+------------------+
5 rows in set (0.00 sec)