如何创建引用相同嵌套 table 的两个变量?
How to create two variables refering the same nested table?
我预计在下面的代码中变量 x
和 y
引用相同的嵌套 table 对象但是表达式 y = x
似乎创建空 table在 y
。所以输出是令人惊讶的'No: a c'(但是我期望'Yes: a b c')。我应该在 PL/SQL 中做什么才能让 y
引用与 x
.
相同的嵌套 table 对象
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;
С(通过引用传递嵌套的 table - 而不是按值)写在 PL/SQL 中还是根本不可能?语言中是否存在任何替代方法来避免该问题?
So output is surprisingly 'No: a c' ( however I expected 'Yes: a b c').
你的期望是错误的。由于两个数组具有不同的值。
让我们一步步来看:
x.extend;
x(x.last) := 'a';
所以,x 的值为 a。
y := x;
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>
PL/SQL 没有引用(但在一个地方我们稍后会看到)所以基本上你要问的在 PL/SQL 中是不可能的。不过,我不明白这怎么会是个问题。
在您的示例中,x
和 y
是两个具有相同类型的不同变量(嵌套 table 集合),x := y
是一个变量赋值(深拷贝), x = y
是一个 comparison. See also e.g. Assigning Values to Variables.
我猜你有一些其他语言的编程背景,你正试图在这里应用一些其他语言范例。你也可能有一个 XY-problem.
一种替代方法是使用两个不同的索引变量来访问集合。这可能适合也可能不适合您的情况:
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;
/
但请注意,对集合的更改会使索引变量无效(这就是我声明常量集合的原因)。
当使用嵌套的 tables 时,还要检查 SQL multiset conditions 以提供强大的操作。
唯一具有引用语义的地方是 subprogram parameters,其中不同的参数模式(IN
、OUT
或 IN OUT
)具有不同的语义(按值传递或按引用传递)。但即使在那里,决定是由 PL/SQL compiler/runtime 做出的 - 程序员没有太多控制权。
我预计在下面的代码中变量 x
和 y
引用相同的嵌套 table 对象但是表达式 y = x
似乎创建空 table在 y
。所以输出是令人惊讶的'No: a c'(但是我期望'Yes: 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;
С(通过引用传递嵌套的 table - 而不是按值)写在 PL/SQL 中还是根本不可能?语言中是否存在任何替代方法来避免该问题?
So output is surprisingly 'No: a c' ( however I expected 'Yes: a b c').
你的期望是错误的。由于两个数组具有不同的值。
让我们一步步来看:
x.extend;
x(x.last) := 'a';
所以,x 的值为 a。
y := x;
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>
PL/SQL 没有引用(但在一个地方我们稍后会看到)所以基本上你要问的在 PL/SQL 中是不可能的。不过,我不明白这怎么会是个问题。
在您的示例中,x
和 y
是两个具有相同类型的不同变量(嵌套 table 集合),x := y
是一个变量赋值(深拷贝), x = y
是一个 comparison. See also e.g. Assigning Values to Variables.
我猜你有一些其他语言的编程背景,你正试图在这里应用一些其他语言范例。你也可能有一个 XY-problem.
一种替代方法是使用两个不同的索引变量来访问集合。这可能适合也可能不适合您的情况:
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;
/
但请注意,对集合的更改会使索引变量无效(这就是我声明常量集合的原因)。
当使用嵌套的 tables 时,还要检查 SQL multiset conditions 以提供强大的操作。
唯一具有引用语义的地方是 subprogram parameters,其中不同的参数模式(IN
、OUT
或 IN OUT
)具有不同的语义(按值传递或按引用传递)。但即使在那里,决定是由 PL/SQL compiler/runtime 做出的 - 程序员没有太多控制权。