立即执行 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;
/