Перебирать таблицу объектов в Oracle - PullRequest
0 голосов
/ 30 мая 2018

Как мне перебрать таблицу таких объектов?

CREATE TYPE SOME_OBJECT AS OBJECT (
  ATTR1 VARCHAR2(20)
, ATTR2 VARCHAR2(30)
);
/

CREATE TYPE C_SOME_OBJECT AS TABLE OF SOME_OBJECT;
/

И ... Я хочу использовать это в качестве параметра для процедуры.Приходится ли его инициализировать в процедуре?

PROCEDURE SOME_PROCEDURE(OBJECT IN C_SOME_OBJECT)
IS
BEGIN
  --Some code here iterating IN parameter
END;

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Вы можете использовать цикл WHILE с FIRST, NEXT, LAST для обработки разреженных коллекций (где элементы были удалены), а также вам необходимо проверить наличие неинициализированных элементов в коллекции:

PROCEDURE SOME_PROCEDURE(
  I_OBJECT IN C_SOME_OBJECT
)
IS
  i PLS_INTERGER;
BEGIN
  -- Check that the collection is not NULL
  IF I_OBJECT IS NULL THEN
    RETURN;
  END IF;

  i := I_OBJECT.FIRST;
  WHILE i IS NOT NULL LOOP
    IF I_OBJECT(i) IS NOT NULL THEN
      DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
    ELSE
      DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
    END;
  END LOOP;
END;
/

Тогда вы можете назвать это:

DECLARE
  o C_SOME_OBJECT := C_SOME_OBJECT();
BEGIN
  o.EXTEND(4);
  o(1) := SOME_OBJECT( '1.1', '1.2' );
                                       -- o(2) IS NULL
  o.DELETE(3);                         -- o(3) has been removed
  o(4) := SOME_OBJECT( '4.1', '4.2' );

  SOME_PROCEDURE( o );
END;
/

Выходы:

1 = (1.1, 1.2)
2 IS NULL
4 = (4.1, 4.2)

Проблемы с FOR ... LOOP:

Использование FOR i IN 1 .. o.COUNT LOOP:

DECLARE
  o C_SOME_OBJECT := C_SOME_OBJECT(
                       SOME_OBJECT( '1.1', '1.2' ),
                       SOME_OBJECT( '2.1', '2.2' ),
                       SOME_OBJECT( '3.1', '3.2' ),
                       SOME_OBJECT( '4.1', '4.2' )
                     );
BEGIN
  o.DELETE(1);

  FOR i IN 1 .. o.COUNT LOOP
    IF I_OBJECT(i) IS NOT NULL THEN
      DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
    ELSE
      DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
    END;
  END LOOP;
 END;
 /

Выходы:

1 IS NULL
2 = (2.1, 2.2)
3 = (3.1, 3.2)

Выводит элемент 1, который не существует, и не выводит элемент 4, который существует.

Использование FOR i IN o.FIRST .. o.LAST LOOP:

DECLARE
  o C_SOME_OBJECT := C_SOME_OBJECT(
                       SOME_OBJECT( '1.1', '1.2' ),
                       SOME_OBJECT( '2.1', '2.2' ),
                       SOME_OBJECT( '3.1', '3.2' ),
                       SOME_OBJECT( '4.1', '4.2' )
                     );
BEGIN
  o.DELETE(2);

  FOR i IN o.FIRST .. o.LAST LOOP
    IF I_OBJECT(i) IS NOT NULL THEN
      DBMS_OUTPUT.PUT_LINE( i || ' = (' I_OBJECT(i).attr1 || ', ' || I_OBJECT(i).attr2 || ')' );
    ELSE
      DBMS_OUTPUT.PUT_LINE( i || ' IS NULL' );
    END;
  END LOOP;
 END;
 /

Выходы:

1 = (1.1, 1.2)
2 IS NULL
3 = (3.1, 3.2)
4 = (4.1, 4.2)

Это выводит 4 элемента (включая удаленный 2-й элемент), когда o.COUNT составляет только 3.

0 голосов
/ 30 мая 2018
-- NOTE #1
-- You cant use Object as name for your input variable because it is a type
-- (Types are reserved words)
PROCEDURE SOME_PROCEDURE(p_SOME_TABLE IN C_SOME_OBJECT)
IS
BEGIN
  FOR i IN p_SOME_TABLE.FIRST .. p_SOME_TABLE.LAST
  LOOP
     -- NOTE #2 Manage it like this
     -- Current iteration: p_SOME_TABLE(i)
     -- Access Example   : p_SOME_TABLE(i).ATTR1

     -- NOTE #3 Or you can assign current iteration to a variable
     -- then use that variable thought it is not by reference if you
     -- do it like this.
  END LOOP;
END;

ОБНОВЛЕНИЕ:

Также будьте осторожны, чтобы не перепутать ЗАПИСИ с ОБЪЕКТАМИ.

ОБЪЕКТ - это тип SQL, но ЗАПИСЬ, с другой стороны, являетсяТип PL / SQL, вы можете думать об этом больше как о C / C ++, как структура.

UPDATE_2:

Обратите внимание, что это не вызовет никаких исключений, если таблицапусто, поэтому вам нужно обработать, если нет данных, например, вы можете использовать .COUNT так:

IF p_SOME_TABLE.COUNT = 0 THEN
   RAISE my_exception;
END IF;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...