我正在使用Oracle apex并尝试使用自动电子邮件进行练习。理想情况下,情况就是如此:用户可以通过他的愿望清单向朋友“推荐”游戏。用户通过复选框选择他们想要推荐的游戏,然后选择朋友和电子邮件内容。我为此准备的代码如下:
DECLARE
content VARCHAR2(4000) := :P4_EMAIL || 'Here are the game(s):';
game VARCHAR2(100);
i NUMBER := 1;
/*Declare the cursor and it's query */
cursor CURSOR IS
SELECT name
from gs_games
where game_id = APEX_APPLICATION.G_F01(i)
FOR UPDATE;
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.count
LOOP
OPEN cursor;
FETCH cursor INTO game;
CLOSE cursor;
END LOOP;
htmldb_mail.Send(p_to => :P4_FRIENDS,
p_from => 'gametracker@gametracker.com',
p_subj => 'Game recommendations from ' || :F56_USER_NAME,
p_body => content || ' ' || game);
END;
这只是部分有效。对于单个选择,每个人都可以完美地工作,但是一旦用户选择了多个游戏,那么电子邮件仅包含已检查的第一个游戏的名称,而不是每个游戏应该包含的名称。我意识到这与我设置光标的方式有关,但我并不完全确定如何在保持循环活动的同时使用它。有没有人有任何想法?谢谢。
答案 0 :(得分:2)
当前的问题是,每次从光标中获取下一行到本地变量game
时,都会覆盖该变量的先前值。一旦从光标中获取了每一行,game
将具有您处理的最后一行的值。
假设您希望您的电子邮件包含以逗号分隔的游戏名称列表,您可以执行类似
的操作-- You probably want to create this function inside of a package that provides other methods
-- for interacting with games
CREATE OR REPLACE FUNCTION get_game_name( p_game_id IN gs_games.game_id%type )
RETURN gs_games.name%type
IS
l_name gs_games.name%type;
BEGIN
SELECT name
INTO l_name
FROM gs_games
WHERE game_id = p_game_id;
RETURN l_name;
END get_game_name;
DECLARE
l_content VARCHAR2(4000) := :P4_EMAIL || 'Here are the game(s):';
l_game_list VARCHAR2(100);
BEGIN
FOR i in 1..APEX_APPLICATION.G_F01.count
LOOP
l_game_list := l_game_list || ', ' || get_game_name( APEX_APPLICATION.G_F01(i) );
END LOOP;
l_game_list := LTRIM( ', ' );
apex_mail.send( p_to => :P4_FRIENDS,
p_from => 'gametracker@gametracker.com',
p_subj => 'Game recommendations from ' || :F56_USER_NAME,
p_body => l_content || ' ' || l_game_list);
END;
关于风格的一些注释
CURSOR
是有问题的,应该不惜一切代价避免。如果你确实需要声明一个游标,你真的应该给它一个有意义的名字。l_
前缀表示局部变量,并使用p_
前缀参数尽管有许多不同的有效约定。这在PL / SQL中很重要,因为SQL语句中的标识符首先使用表中的列名称然后使用局部变量来解析。这使得很容易无意中编写使用的代码当你想要使用局部变量时,如果你没有一些约定来明确你正在使用的那个列的话。SELECT INTO
。 name
的{{1}},因为这样可以最大限度地重复使用 - 可能还有很多其他地方需要做类似的事情,所以你想写一下代码一次,并多次使用它。将game_id
放入匿名PL / SQL块的循环中是完全合法的,最好将该代码分解为函数。SELECT INTO
包,而不是旧的apex_mail
包。两者之间不应该有任何功能差异,但HTML DB是很多版本之前Oracle APEX的旧名称,所以逐步淘汰旧包名称的使用是个好主意。