PL / SQL Динамический SQL в функции с одинарными кавычками

#oracle #dynamic #plsql

#Oracle #динамический #plsql

Вопрос:

Ниже приведена функция, которую мне нужно выполнить.

 create or replace function GET_FROM_ANY_STD2(TheValue in varchar2, TheTableName in varchar2, TheContext in varchar2)
return varchar2
is GET_FROM_ANY_STD2 varchar2(10000);
begin

select listagg(value0, '@') within group (order by rn) into GET_FROM_ANY_STD2
from (
 execute immediate
       'select levels.column_value rn,
              trim (regexp_substr(TheValue, '[^@] ', 1, levels.column_value)) as did
              from dual t, table(cast(multiset(select level
                                                from dual connect by level <= length(regexp_replace(**TheValue**, '[^@] '))   1)
              as sys.odcinumberlist)) levels) t
       left join **TheTableName** d on d.code0 = t.did and d.context =**TheContext**;
       return(GET_FROM_ANY_STD2);'
end;
 

но когда я пытаюсь выполнить это, я получаю несколько ошибок.
все значения между двойными звездочками должны быть параметром.
Я пробовал несколько вещей, но ни одна из них не увенчалась успехом: (
Я приветствую любую помощь.
С наилучшими пожеланиями,
Мурат

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

1. Нет return инструкции. Что он должен делать?

Ответ №1:

Я не уверен, что должен делать этот фрагмент кода, поскольку возвращает то, на что вы никогда не ссылались в своем коде: listagg(value0 ...) — что такое value0 ?

В любом случае, просто чтобы показать, как это должно быть сделано, держи.

Примерная таблица:

 SQL> CREATE TABLE thetablename
  2  AS
  3     SELECT '0' code0, 'context' AS context FROM DUAL;

Table created.
 

Функция: при использовании динамического SQL вам необходимо объединить параметры с остальной частью кода. Это некрасиво, сложно для отладки, сложно для чтения, сложно для записи (проблемы с одинарными кавычками), вы должны знать о возможной SQL-инъекции (читайте о dbms_assert ).

Я попытался сделать это как можно более простым, составив инструкцию SQL в отдельной переменной ( l_str ), а затем просто выполнить ее результат в retval .

 SQL> CREATE OR REPLACE FUNCTION get_from_any_std2 (TheValue      IN VARCHAR2,
  2                                                TheTableName  IN VARCHAR2,
  3                                                TheContext    IN VARCHAR2)
  4     RETURN VARCHAR2
  5  IS
  6     l_str   VARCHAR2 (10000);
  7     retval  VARCHAR2 (10000);
  8  BEGIN
  9     l_str :=
 10           'WITH
 11        trows
 12        AS
 13           (SELECT t.COLUMN_VALUE rn,
 14                   TRIM (REGEXP_SUBSTR ( '
 15        || CHR (39)
 16        || TheValue
 17        || CHR (39)
 18        || ',
 19                                        ''[^@] '',
 20                                        1,
 21                                        t.COLUMN_VALUE)) AS did
 22              FROM DUAL t
 23                   CROSS JOIN
 24                   TABLE (
 25                      CAST (
 26                         MULTISET (
 27                                SELECT LEVEL
 28                                  FROM DUAL
 29                            CONNECT BY LEVEL <=
 30                                         LENGTH (
 31                                            REGEXP_REPLACE ( '
 32        || CHR (39)
 33        || thevalue
 34        || CHR (39)
 35        || ',
 36                                                            ''[^@] ''))
 37                                         1)
 38                            AS SYS.odcinumberlist)) t)
 39     SELECT LISTAGG (t.did, ''@'') WITHIN GROUP (ORDER BY t.rn)
 40       FROM trows t
 41            LEFT JOIN '
 42        || TheTableName
 43        || ' d
 44               ON     d.code0 = t.did
 45                  AND d.context = '
 46        || CHR (39)
 47        || TheContext
 48        || CHR (39);
 49
 50     EXECUTE IMMEDIATE l_str
 51        INTO retval;
 52
 53     RETURN retval;
 54  END;
 55  /

Function created.
 

Тестирование:

 SQL> SET VERIFY OFF
SQL>
SQL> SELECT get_from_any_std2 ( 'amp;thevalue', 'amp;thetablename', 'amp;thecontext') result
  2    FROM DUAL;
Enter value for thevalue: 0@abc@def
Enter value for thetablename: thetablename
Enter value for thecontext: context

RESULT
--------------------------------------------------------------------------------
0@abc@def

SQL>
 

Итак, да — он что-то делает и что-то возвращает. Я понятия не имею, действительно ли это то, чего вы хотели, но — теперь, когда вы знаете, как это сделать, сделайте это.

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

1. К сожалению, это не правильно. У меня есть таблица с именем std и некоторые другие таблицы поиска с такой же структурой.

2. Структура следующая: создайте таблицу STD (контекст VARCHAR2(30), code0 VARCHAR2(3), value0 VARCHAR2(254), value1 VARCHAR2(254), value2 VARCHAR2(254), value3 VARCHAR2(254), value4 VARCHAR2(254), флаги INTEGER, upid VARCHAR2(21), НОМЕР upd_cnt(3) по умолчанию 0 не равен нулю, идентификационный НОМЕР (10) не равен нулю, last_modified ДАТА, last_modified_user VARCHAR2(30), create_date ДАТА, create_user VARCHAR2(30) )

3. допустим, данные для таблицы STD следующие: context, code0, value0 «a», «x», «x1» «a», «y», «y1» «b», «z», «z2» «a», «z», «z1»

4. основная цель — получить строку «x1 @z1», когда входные данные являются; Значение = ‘a @z’, имя_таблицы = ‘STD’, текст = ‘a’.

5. Основной sqp достигает цели без параметризованного имени таблицы. Это то, что мне нужно выполнить…