tir*_*hen 7 mysql sql stored-procedures cursor
如何在同一例程中使用两个游标?如果我删除第二个游标声明和获取循环everthing工作正常.该例程用于在我的webapp中添加朋友.它需要当前用户的id和我们想要添加为朋友的朋友的电子邮件,然后它检查电子邮件是否具有相应的用户ID,如果不存在朋友关系,则会创建一个.除了这个之外的任何其他常规解决方案也会很棒.
DROP PROCEDURE IF EXISTS addNewFriend;
DELIMITER //
CREATE PROCEDURE addNewFriend(IN inUserId INT UNSIGNED, IN inFriendEmail VARCHAR(80))
BEGIN
DECLARE tempFriendId INT UNSIGNED DEFAULT 0;
DECLARE tempId INT UNSIGNED DEFAULT 0;
DECLARE done INT DEFAULT 0;
DECLARE cur CURSOR FOR
SELECT id FROM users WHERE email = inFriendEmail;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
REPEAT
FETCH cur INTO tempFriendId;
UNTIL done = 1 END REPEAT;
CLOSE cur;
DECLARE cur CURSOR FOR
SELECT user_id FROM users_friends WHERE user_id = tempFriendId OR friend_id = tempFriendId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
REPEAT
FETCH cur INTO tempId;
UNTIL done = 1 END REPEAT;
CLOSE cur;
IF tempFriendId != 0 AND tempId != 0 THEN
INSERT INTO users_friends (user_id, friend_id) VALUES(inUserId, tempFriendId);
END IF;
SELECT tempFriendId as friendId;
END //
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
Oct*_*adu 17
以下是如何在同一例程中使用两个游标的简单示例:
DELIMITER $$
CREATE PROCEDURE `books_routine`()
BEGIN
DECLARE rowCountDescription INT DEFAULT 0;
DECLARE rowCountTitle INT DEFAULT 0;
DECLARE updateDescription CURSOR FOR
SELECT id FROM books WHERE description IS NULL OR CHAR_LENGTH(description) < 10;
DECLARE updateTitle CURSOR FOR
SELECT id FROM books WHERE title IS NULL OR CHAR_LENGTH(title) <= 10;
OPEN updateDescription;
BEGIN
DECLARE exit_flag INT DEFAULT 0;
DECLARE book_id INT(10);
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET exit_flag = 1;
updateDescriptionLoop: LOOP
FETCH updateDescription INTO book_id;
IF exit_flag THEN LEAVE updateDescriptionLoop;
END IF;
UPDATE books SET description = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' WHERE books.id = book_id;
SET rowCountDescription = rowCountDescription + 1;
END LOOP;
END;
CLOSE updateDescription;
OPEN updateTitle;
BEGIN
DECLARE exit_flag INT DEFAULT 0;
DECLARE book_id INT(10);
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET exit_flag = 1;
updateTitleLoop: LOOP
FETCH updateTitle INTO book_id;
IF exit_flag THEN LEAVE updateTitleLoop;
END IF;
UPDATE books SET title = 'Lorem ipsum dolor sit amet' WHERE books.id = book_id;
SET rowCountTitle = rowCountTitle + 1;
END LOOP;
END;
CLOSE updateTitle;
SELECT 'number of titles updated =', rowCountTitle, 'number of descriptions updated =', rowCountDescription;
END
Run Code Online (Sandbox Code Playgroud)
我终于写了一个不同的函数来做同样的事情:
DROP PROCEDURE IF EXISTS addNewFriend;
DELIMITER //
CREATE PROCEDURE addNewFriend(IN inUserId INT UNSIGNED, IN inFriendEmail VARCHAR(80))
BEGIN
SET @tempFriendId = (SELECT id FROM users WHERE email = inFriendEmail);
SET @tempUsersFriendsUserId = (SELECT user_id FROM users_friends WHERE user_id = inUserId AND friend_id = @tempFriendId);
IF @tempFriendId IS NOT NULL AND @tempUsersFriendsUserId IS NULL THEN
INSERT INTO users_friends (user_id, friend_id) VALUES(inUserId, @tempFriendId);
END IF;
SELECT @tempFriendId as friendId;
END //
DELIMITER ;
Run Code Online (Sandbox Code Playgroud)
我希望这是一个更好的解决方案,无论如何它都可以正常工作。感谢您告诉我在不必要时不要使用光标。
| 归档时间: |
|
| 查看次数: |
49783 次 |
| 最近记录: |