ВЫПОЛНИТЬ НЕМЕДЛЕННЫЕ результаты в Тип таблицы - PullRequest
0 голосов
/ 23 октября 2019

Мне нужно, чтобы EXECUTE IMMEDIATE возвращал свои результаты в табличный тип (AS TABLE OF)

Если немедленное выполнение возвращает одно значение, я могу сохранить результат, используя INTO somevariable

Но, мой немедленный запуск вернет таблицу с несколькими столбцами, и никакие гугли не помогут мне разобраться!

Сначала я создаю типы

CREATE OR REPLACE TYPE T_VALIDITY_RECORD AS OBJECT (
   TIME_COL  DATE,
   VALUE_COL NUMBER
);
/

CREATE OR REPLACE TYPE T_VALIDITY_TABLE AS TABLE OF T_VALIDITY_RECORD;
/

Затем я пытаюськод

DECLARE
   RET_TABLE   T_VALIDITY_TABLE;
BEGIN

EXECUTE IMMEDIATE 'SELECT my_date,
                          my_numbers  
                   FROM   my_table
                   WHERE  somthing = somthingelse' INTO RET_TABLE;
END;

Это просто упрощенный пример, реальный код делает (будет делать другие вещи)

Я пробовал разные вещи, такие как BULK COLLECT INTO и т. д., но не могупохоже, он работает.

Я получаю следующую ошибку:

Отчет об ошибке
ORA-00932: несовместимые типы данных: ожидается - получил -
ORA-06512: в строке 5
00932. 00000 - "несовместимые типы данных: ожидается% s получено% s"
* Причина:
* Действие:

Ответы [ 2 ]

1 голос
/ 23 октября 2019

Вам нужно BULK COLLECT INTO, и вам нужно собирать экземпляры T_VALIDITY_OBJECT, а не пар NUMBER и DATE значений.

Oracle Setup :

CREATE OR REPLACE TYPE T_VALIDITY_RECORD AS OBJECT (
   VALUE_COL NUMBER,
   TIME_COL  DATE
);
/

CREATE OR REPLACE TYPE T_VALIDITY_TABLE AS TABLE OF T_VALIDITY_RECORD;
/

CREATE TABLE my_table ( my_date, my_number, something ) AS
SELECT 1, DATE '2019-01-01', 1 FROM DUAL UNION ALL
SELECT 2, DATE '2019-01-02', 1 FROM DUAL UNION ALL
SELECT 3, DATE '2019-01-03', 1 FROM DUAL;

PL / SQL :

DECLARE
  RET_TABLE   T_VALIDITY_TABLE;
BEGIN
  EXECUTE IMMEDIATE 'SELECT T_VALIDITY_RECORD( my_date, my_number )
                     FROM   my_table
                     WHERE  something = :value'
    BULK COLLECT INTO RET_TABLE
    USING 1;

  FOR i IN 1 .. RET_TABLE.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE( i || ': ' || ret_table(i).time_col || ', ' || ret_table(i).value_col );
  END LOOP;
END;
/

Вывод :

1: 2019-01-01 00:00:00, 1
2: 2019-01-02 00:00:00, 2
3: 2019-01-03 00:00:00, 3

дБ <> скрипка здесь

1 голос
/ 23 октября 2019

Некоторые проблемы:

Вы извлекаете два столбца в структуру, которая имеет только один элемент, состоящий из двух значений.

Кроме того, если ваш выбор может дать более одной строки, вынужен BULK COLLECT.

Если вам не нужен строго динамический SQL, здесь будет работать простой SQL-запрос:

DECLARE
   RET_TABLE   T_VALIDITY_TABLE;
BEGIN    
    SELECT T_VALIDITY_RECORD(my_date, my_numbers  )
          bulk collect INTO RET_TABLE
   FROM   my_table ;
END;

Если вам нужен динамический SQL по другим причинам:

DECLARE
   RET_TABLE   T_VALIDITY_TABLE;
BEGIN
    execute immediate ' SELECT T_VALIDITY_RECORD(my_date,
                              my_numbers  )
                        FROM   my_table'   
          bulk collect INTO RET_TABLE;                   
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...