立即执行 oracle 字符串连接问题
execute immediate oracle string concatenate issue
我在连接要立即执行的字符串时遇到问题。任何人都知道以下声明有什么问题。
立即执行 '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
局部变量
之前需要 3 个单引号,之后需要 4 个单引号
'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
不应该是 modifiable without a database restart。我见过有人说他们已经能够在运行时使用 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;
/
我在连接要立即执行的字符串时遇到问题。任何人都知道以下声明有什么问题。
立即执行 '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
不应该是 modifiable without a database restart。我见过有人说他们已经能够在运行时使用 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;
/