Я ожидал, что в следующем коде переменные x
и y
относятся к одному и тому же объекту вложенной таблицы, но выражение y = x
, похоже, создает пустую таблицу в y
. Таким образом, результат неожиданно оказался «Нет: a c» (хотя я ожидал «Да: a b c» ). Что мне делать в PL / SQL, чтобы y
ссылался на тот же объект вложенной таблицы, что и x
.
declare
type str_t is table of varchar(100);
x str_t := str_t ();
y str_t ;
begin
x.extend; x(x.last) := 'a';
y := x;
y.extend; y(y.last) := 'b';
x.extend; x(x.last) := 'c';
dbms_output.put_line(case when x=y then 'Yes: ' else 'No: ' end);
for i in x.first .. x.last
loop
dbms_output.put_line(x(i));
end loop;
Можно ли (передать вложенную таблицу по ссылке, а не по значению) на PL / SQL или это принципиально невозможно? Существуют ли какие-либо альтернативы в языке для решения проблемы?
2 ответа
PL / SQL не имеет ссылок (но в одном месте мы увидим позже), поэтому, по сути, то, что вы просите, невозможно в PL / SQL. Однако я не понимаю, как это может быть проблемой.
В вашем примере x
и y
- две разные переменные одного типа (коллекция вложенных таблиц), x := y
- присвоение переменной (глубокая копия), x = y
представляет собой сравнение. См. Также, например, Присвоение значений переменным.
Я предполагаю, что у вас есть опыт программирования с некоторыми другими языками, и вы пытаетесь применить здесь какую-то другую языковую парадигму. У вас также может быть проблема XY.
Одна альтернатива - использовать две разные индексные переменные для доступа к коллекции. Это может или не может подойти для вашего случая:
declare
type str_list_t is table of varchar2(32767);
v_foos constant str_list_t := str_list_t('a', 'b', 'c');
-- have some business logic to get the right indices
i pls_integer := 1;
j pls_integer := 3;
begin
dbms_output.put_line(v_foos(i));
dbms_output.put_line(v_foos(j));
end;
/
Но обратите внимание, что изменения в коллекции сделают недействительными индексные переменные (поэтому я объявил постоянную коллекцию).
При работе с вложенными таблицами также проверьте условия мультимножества SQL a> которые обеспечивают мощные манипуляции.
Единственное место с эталонной семантикой - это параметры подпрограммы где разные режимы параметров (IN
, OUT
или IN OUT
) имеют разную семантику (передача по значению или передача по ссылке). Но даже там решение принимает компилятор / среда выполнения PL / SQL - у программиста нет особого контроля.
Таким образом, на удивление выводится «Нет: a c» (хотя я ожидал «Да: a b c»).
Ваше ожидание неверно. Поскольку два массива имеют разные значения.
Посмотрим пошагово:
x.extend;
x (x.last): = 'а';
Итак, x имеет значение a .
у: = х;
x копируется в y , поэтому y имеет значение a .
y.extend;
y (y.last): = 'b';
Теперь у y есть a и b .
x.extend;
x (x.last): = 'c';
Теперь у x есть a и c .
В заключение,
X --> a,c
Y --> a,b
Посмотрим, что ваш код показывает результат:
SQL> set serveroutput on
SQL> DECLARE
2 type str_t
3 IS
4 TABLE OF VARCHAR(100);
5 x str_t := str_t ();
6 y str_t ;
7 BEGIN
8 x.extend;
9 x(x.last) := 'a';
10 y := x;
11 y.extend;
12 y(y.last) := 'b';
13 x.extend;
14 x(x.LAST) := 'c';
15 FOR i IN x.first .. x.last
16 LOOP
17 dbms_output.put_line('X'||'-'||x(i));
18 END LOOP;
19 FOR i IN y.first .. y.last
20 LOOP
21 dbms_output.put_line('Y'||'-'||y(i));
22 END LOOP;
23 END;
24 /
X-a
X-c
Y-a
Y-b
PL/SQL procedure successfully completed.
SQL>
Итак, X и Y не равны.
Чтобы сделать их равными, установите Y = X :
SQL> set serveroutput on
SQL> DECLARE
2 type str_t
3 IS
4 TABLE OF VARCHAR(100);
5 x str_t := str_t ();
6 y str_t ;
7 BEGIN
8 x.extend;
9 x(x.LAST) := 'a';
10 x.extend;
11 x(x.last) := 'b';
12 x.extend;
13 x(x.LAST) := 'c';
14 y := x;
15 dbms_output.put_line(case when x=y then 'Yes: ' else 'No: ' end);
16 FOR i IN x.first .. x.last
17 LOOP
18 dbms_output.put_line('X'||'-'||x(i));
19 END LOOP;
20 END;
21 /
Yes:
X-a
X-b
X-c
PL/SQL procedure successfully completed.
SQL>
Похожие вопросы
Новые вопросы
oracle
Oracle Database - это многомодельная система управления базами данных, созданная корпорацией Oracle. НЕ используйте этот тег для других продуктов, принадлежащих Oracle, таких как Java и MySQL.