SQL — Escape-строки (база данных ORACLE)

#sql #database #oracle #plsql

Вопрос:

Я немного переживаю по этому поводу, может быть, кто-то видит что-то, чего не вижу я…

 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;
 

Почему-то я не нахожу способа избежать струн, что я делаю не так?

Заранее спасибо

Комментарии:

1. Вместо того, чтобы иметь динамические имена таблиц для каждого месяца, вы можете рассмотреть возможность разделения

2. Должна ли она быть динамичной? Похоже, что вы можете построить имя таблицы как TABLENAME_2021_07 , а затем просто передать его в dbms_stats.gather_table_stats как обычно.

Ответ №1:

Здесь используется обратный подход, начинающийся с результата и ведущий к выражению результата

  • Начните с строки результата
     BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_2021_07'), cascade => true, no_invalidate => false); END;
     
  • Разделите его на статическую и динамическую части
      BEGIN dbms_stats.gather_table_stats('SCHEMA', 'TABLENAME_
     2021_07                                                         <--- dynamic
     '), cascade => true, no_invalidate => false); END;
     
  • заключите статические части в q-кавычки (чтобы вам не нужно было убегать!), замените динамическую часть выражением и совместите все части с ||

Добавьте в запрос select:

  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;
 

Комментарии:

1. Привет, спасибо за ваш ответ, единственная проблема здесь-это «после ИМЕНИ ТАБЛИЦЫ» с этим запросом, который я получаю: «ИМЯ ТАБЛИЦЫ». Есть идеи?

2. @MladenNikolic . . . Я передвинул заключительную цитату.

Ответ №3:

Используйте механизм q-кавычек, это упрощает задачу (вам не нужно избегать одинарных кавычек).:

 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
  • далее следует одна цитата
  • за ним следует скобка (используйте ту, которая не является частью строки!)
  • теперь напишите свое заявление так, как вы бы сделали, если бы оно не было заключено в одинарные кавычки
  • завершите его закрывающей скобой …
  • … и завершающая одинарная цитата

Комментарии:

1. Привет, спасибо за ваш ответ, могу ли я использовать несколько механизмов цитирования вопросов в одном операторе select? поскольку функции trunc() необходимо вычислить фактическую дату в строке, она этого не делает, поэтому я полагаю, что мне нужно разделить ее от строки, верно?

2. В коде, который вы опубликовали (и который я использовал повторно), есть 2 опечатки: 'YYYY-MM')' : в имени таблицы не может быть тире (вероятно, следует подчеркнуть), и последняя одинарная кавычка должна быть удалена. Что касается вашего вопроса: вам не нужно использовать механизм несколько раз (но вы можете). Хотя, если вы исправите то, что я только что написал (и исправили в ответе), это может сработать нормально.

3. Задача здесь состоит в том, чтобы не «избежать» || конкатенаций в q-строке. Что, конечно, работает, но дает другой результат. Я знаю это по собственному тяжелому опыту;)

Ответ №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'[ в начало и ]' в конец.