我在连接要立即执行的字符串时遇到问题。有人知道下面的陈述有什么问题吗?
EXECUTE IMMEDIATE 'ALTER SESSION SET smtp_out_server = " ||SMTPServer|| " ';
select smtpserver into SMTPServer from mytable;
if(SMTPServer is not null)
then
EXECUTE IMMEDIATE 'ALTER SESSION SET smtp_out_server = ''||SMTPServer||''';
--*****above does not work, below does work****
EXECUTE IMMEDIATE 'ALTER SESSION SET smtp_out_server = ''10.1.1.1''';
从构建所需字符串的角度来看,您缺少了两个单引号。在SMTPServer
局部变量
'ALTER SESSION SET smtp_out_server = ''' || smtpServer || ''''
就我个人而言,我发现这样做更容易,你声明一个模板(使用q引号语法,因为它嵌入了单引号),调用replace
来替换模板值,然后调用EXECUTE IMMEDIATE
。虽然代码有点多,但总的来说,它使工作更容易。
l_sql_stmt := q'{ALTER SESSION SET smtp_out_server = '##server##'}';
l_sql_stmt := replace( l_sql_stmt, '##server##', smtpServer );
EXECUTE IMMEDIATE l_sql_stmt;
你确定第二个语句真的有效吗?在没有数据库重启的情况下,不应该修改smtp_out_server
。我看到有人说,他们已经能够在运行时使用ALTER SYSTEM
成功地修改它,但还没有看到有人尝试使用ALTER SESSION
。我会犹豫是否要构建依赖于违背文档的行为的代码。如果您需要在运行时控制您正在使用的SMTP服务器,我强烈建议使用utl_smtp
包而不是utl_mail
。
为EXECUTE IMMEDIATE提供替换参数的语句并不是很好,因为对于优化器来说,每次都是完全不同的语句,因此它为每个语句准备另一个执行计划。你应该在你的EXECUTE IMMEDIATE子句中使用绑定。
的例子:
DECLARE
SMTPServer mytable.smtpserver%type;
l_set_smtpserver_stmt VARCHAR2(600) := q'#ALTER SESSION SET smtp_out_server = ':p_smtp_server'#'
BEGIN
SELECT smtpserver INTO SMTPServer FROM mytable;
IF SMTPServer IS NOT NULL THEN
EXECUTE IMMEDIATE l_set_smtpserver_stmt USING SMTPServer;
END IF;
EXCEPTION
-- handle no_data_found exception since you're using select .. into statement
WHEN NO_DATA_FOUND THEN
-- handle exception
WHEN OTHERS THEN
-- handle exception
END;
/