6

一部の列にネストされたテーブルがあるOracleテーブルがあります。ここで、メインテーブルの各レコードで、ネストされた各テーブルのすべてのレコードを更新できるようにする必要があります。これはどのように達成されますか?私が試した方法のいずれかで、そのビューで更新を実行できないか、単一行のサブクエリが複数の行を返すというエラーが発生します。

これが説明のための例です。私はこのような更新を実行できます:

    UPDATE TABLE(select entity.name
                 from entity
                 where entity.uidn = 2)
    SET last = 'Decepticon',
    change_date = SYSDATE,
    change_user = USER
    WHERE first = 'Galvatron';

ただし、この場合、table句は、単一の行から単一のネストされたテーブルで実行されます。2に等しいentity.uidnだけが必要ない場合、このような更新はどのように実行されますか?

ありがとう!

4

1 に答える 1

10

おそらく、データベースでネストされたテーブルを避ける最も良い理由は、それらが扱いにくく、構文が十分に文書化されておらず、理解しにくいということです。

先に進みます!

これは、ネストされたテーブルを持つテーブルです。

SQL> select f.force_name, t.id, t.name
  2  from transformer_forces f, table(f.force_members) t
  3  /

FORCE_NAME         ID NAME
---------- ---------- --------------------
Autobot             0 Metroplex
Autobot             0 Optimus Prime
Autobot             0 Rodimus
Decepticon          0 Galvatron
Decepticon          0 Megatron
Decepticon          0 Starscream
Dinobot             0 Grimlock
Dinobot             0 Swoop
Dinobot             0 Snarl

9 rows selected.

SQL>

ご覧のとおり、ネストされたテーブルの各要素の ID 属性は、常にゼロに設定されています。私たちがやりたいことは、それらすべてを更新することです。しかし悲しいかな!

SQL> update table
  2   ( select force_members from transformer_forces ) t
  3  set t.id = rownum
  4  /
 ( select force_members from transformer_forces ) t
   *
ERROR at line 2:
ORA-01427: single-row subquery returns more than one row


SQL> 

ネストされたテーブルのすべての要素を保持テーブルの 1 つの行に対して更新することができます。

SQL> update table
  2       ( select force_members from transformer_forces
  3         where force_name = 'Autobot') t
  4      set t.id = rownum
  5  /

3 rows updated.

SQL>

しかし、テーブル全体に対してこれを行う唯一の方法は、PL/SQL ループですうん!

別の方法があります: NESTED_TABLE_GET_REFS ヒントを介してNested Table Locator を使用します。これは特にあいまいなことです (ヒントのメイン リストにはありません) が、トリックは実行されます。

SQL> update /*+ NESTED_TABLE_GET_REFS */ force_members_nt
  2  set id = rownum
  3  /

9 rows updated.

SQL> select f.force_name, t.id, t.name
  2  from transformer_forces f, table(f.force_members) t
  3  /

FORCE_NAME         ID NAME
---------- ---------- --------------------
Autobot             1 Metroplex
Autobot             2 Optimus Prime
Autobot             3 Rodimus
Decepticon          4 Galvatron
Decepticon          5 Megatron
Decepticon          6 Starscream
Dinobot             7 Grimlock
Dinobot             8 Swoop
Dinobot             9 Snarl

9 rows selected.

SQL>

このヒントにより、保持テーブルを完全にバイパスして、実際のネストされたテーブルを操作できます。つまり、ネストした表の記憶域句で指定されたオブジェクト:

create table transformer_forces (
    force_name varchar2(10)
    , force_members transformers_nt)
nested table force_members store as force_members_nt return as value;
                                    ^^^^^^^^^^^^^^^^
于 2010-07-15T19:34:25.340 に答える