【问题标题】:SQL - Escape strings (ORACLE DB)SQL - 转义字符串 (ORACLE DB)
【发布时间】:2021-09-14 08:11:13
【问题描述】:

我对此有点挣扎,也许有人看到了我没有看到的东西......

select 'BEGIN dbms_stats.gather_table_stats('''SCHEMA'', ''TABLENAME_'' || to_char(trunc(sysdate, 'MM'), 'YYYY-MM')', cascade => true, no_invalidate => false); END;' from dual;

所以输出应该是:

BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_2021_07'), cascade => true, no_invalidate => false); END;

不知怎的,我没有找到逃避字符串的方法,我做错了什么?

提前致谢

【问题讨论】:

  • 我考虑分区而不是每个月都有动态表名
  • 需要动态吗?看起来您可以将表名构造为TABLENAME_2021_07,然后照常将其传递给 dbms_stats.gather_table_stats。

标签: sql database oracle plsql


【解决方案1】:

这里是颠倒的方法,以结果开头并引导结果表达式

  • 结果字符串开始

    BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_2021_07'), cascade => true, no_invalidate => false); END;
    
  • 把它分成staticdynamic部分

     BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_
     2021_07                                                         <--- dynamic
     '), cascade => true, no_invalidate => false); END;
    
  • static 部分用 q 引号括起来(这样您就不必转义了!),将 dynamic 部分替换为表达式并将所有部分与 @987654323 连接起来@

添加一个选择查询:

 select
       q'[BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_]' ||
       to_char(trunc(sysdate, 'MM'), 'YYYY-MM') ||                                                     
       q'['), cascade => true, no_invalidate => false); END;]'
    from dual;

【讨论】:

    【解决方案2】:

    如果我理解正确:

    select 'BEGIN dbms_stats.gather_table_stats(''SCHEMA'', ''TABLENAME_' ||
           to_char(trunc(sysdate, 'MM'), 'YYYY-MM') ||
           ''', cascade => true, no_invalidate => false); END;'
    from dual;
    

    【讨论】:

    • 嗨,谢谢你的回答,这里唯一的问题是在 TABLENAME 之后我得到的查询是 ':'TABLENAME'_DATE 有什么想法吗?
    • @MladenNikolic 。 . .我移动了结束语。
    【解决方案3】:

    使用q-quoting机制,它更简单(你不必转义单引号):

    SELECT q'[BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_' || to_char(trunc(sysdate, 'MM'), 'YYYY_MM'), cascade => true, no_invalidate => false); END;]' result
      FROM DUAL;
    

    导致

    BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_' || to_char(trunc(sysdate, 'MM'), 'YYYY_MM'), cascade => true, no_invalidate => false); END;
    

    您的陈述很长,因此很难看到,所以 - 这是一个简化的示例,说明如何做到这一点:

    SQL> select 'stats(''schema'')' old_result,
      2         q'[stats('schema')]' new_result
      3  from dual;
    
    OLD_RESULT      NEW_RESULT
    --------------- ---------------
    stats('schema') stats('schema')
    
    SQL>
    
    • q
    • 后跟单引号
    • 后跟括号(使用不属于字符串的那个!)
    • 现在,写下你的陈述,如果它没有用单引号括起来的话
    • 用右括号结束它...
    • ...和一个终止单引号

    【讨论】:

    • 您好,谢谢您的回答,我可以在单个 select 语句中使用多个 q-quoting 机制吗?由于 trunc() 函数需要计算字符串中的实际日期,所以我想我需要将它从字符串中除以对吗?
    • 您发布的代码中有 2 个拼写错误(我重用了),这里:'YYYY-MM')':表名不能有破折号(应该是下划线),最后一个单引号应该是删除。至于您的问题:您不必多次使用该机制(但您可以)。不过,如果您修复了我刚刚写的内容(并且也修复了答案),它可能可以正常工作。
    • 这里的挑战是“转义”q-string中的||连接。哪个当然有效,但会产生不同的结果。我从自己的经验中知道;)
    【解决方案4】:

    你想要:

    select 'BEGIN dbms_stats.gather_table_stats(''SCHEMA'', ''TABLENAME_'
           || to_char(sysdate, 'YYYY_MM')
           || ''', cascade => true, no_invalidate => false); END;'
    from   dual;
    

    我发现格式化它很有帮助,以便静态和动态部分位于不同的行,然后您可以写出静态字符串,然后将所有引号加倍以转义它们,并在开头和结尾放置一个前导和尾随引号字符串字面量。

    或者,如果你想要一个带 q 引号的字符串文字:

    select q'[BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_]'
           || to_char(sysdate, 'YYYY_MM')
           || q'[', cascade => true, no_invalidate => false); END;]'
    from   dual;
    

    只需写出您的静态字符串并在开头添加q'[,在末尾添加]'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-11
      • 2013-04-14
      • 1970-01-01
      • 2015-07-06
      • 1970-01-01
      • 2015-01-07
      相关资源
      最近更新 更多