Ссылка на вложенную таблицу в запросе реляционной вставки - PullRequest
1 голос
/ 05 апреля 2011

Ниже приведены типы объектов, которые у меня есть. По сути, у меня есть таблица персоны и дочерняя таблица как вложенная таблица персоны.

У меня есть школьный стол с отношением M: N к дочернему столу (вложенный). Поэтому я создаю промежуточную таблицу для вставки данных child_school.

enter image description here

Как создать промежуточную таблицу и вставить данные?

create type school_t as object(
    sid number(5,2),
    name varchar(20))
/

create type child_t as object(
    cid number(5,2),
    name varchar(20))
/

create type childtable_t as table of child_t
/

create type person_t as object(
    pid number(5,2),
    name varchar(20),
    child childtable_t)
/

create table person_tab of person_t(
    pid primary key
)nested table child store as child_table
/

create table school_tab of school_t
/

- есть какая-то проблема. Ниже не работает.

create type school_child_t as object(
    cid ref person_t,
    sid ref school_t)
/

create table school_child_tab of school_child_t(
    cid references person_tab,
    sid references school_tab
)
/

- Вот что я хочу сделать

create table school_child_tab(
    cid number(5,2) references childtable_t,
    sid number(5,2) references school_tab
)
/

Ссылка на cid должна быть ссылкой во вложенной таблице. Проблема в этом.

Ответы [ 2 ]

4 голосов
/ 05 апреля 2011

Я видел ваше редактирование и собирался сказать вам, что невозможно ссылаться на вложенную таблицу извне.

Вложенная таблица физически создается как отдельная таблица, которая содержит данные отдельно от родительской таблицы:

SQL> SELECT object_name, object_type
  2    FROM all_objects
  3   WHERE created > trunc(sysdate)
  4     AND object_type = 'TABLE';

OBJECT_NAME                    OBJECT_TYPE
------------------------------ -------------------
SCHOOL_TAB                     TABLE
CHILD_TABLE                    TABLE
PERSON_TAB                     TABLE

Здесь вы можете видеть, что Oracle создал таблицу CHILD_TABLE, однако она скрыта от нас и может работать только внутри Oracle:

SQL> select * from child_table;

ORA-22812: cannot reference nested table column's storage table

В этом случае я былЯ почти уверен, что вы не можете ссылаться на дочернюю таблицу каким-либо образом, однако, к моему удивлению, это работает (мы не можем выбрать из CHILD_TABLE, однако мы можем ссылаться на него):

SQL> alter table child_table add constraint pk_child_table primary key (cid);

Table altered

SQL> CREATE TABLE school_child_tab (
  2     cid REFERENCES child_table,
  3     sid REFERENCES school_tab
  4  );

Table created

Выможет создать ваши вставки, как это (я не очень люблю хранить данные как объекты, но здесь вы идете):

SQL> insert into school_tab values (school_t(1, 'school A'));

1 row inserted

SQL> insert into person_tab values (
  2      person_t(1, 'person A', childtable_t(child_t(1, 'child A'))));

1 row inserted

SQL> insert into school_child_tab values (1, 1);

1 row inserted
2 голосов
/ 05 апреля 2011

Я немного изменил вашу модель данных:

SQL> create type school_t as object(
  2      sid number(5,2),
  3      name varchar(20))
  4  /

Type created.

SQL> create type child_t as object(
  2      cid number(5,2),
  3      name varchar(20))
  4  /

Type created.

SQL> create table school_tab of school_t
  2  /

Table created.

SQL> create table child_tab  of child_t
  2  /

Table created.

SQL>

Давайте заполним вложенные таблицы:

SQL> insert into child_tab
  2      values (111, 'Fred')
  3  /

1 row created.

SQL> insert into child_tab
  2      values (112, 'Ayesha')
  3  /

1 row created.

SQL> insert into child_tab
  2      values (113, 'Aadil')
  3  /

1 row created.

SQL> insert into school_tab
  2      values (222, 'Bash Street')
  3  /

1 row created.

SQL> insert into school_tab
  2      values (223, 'Greyfriars')
  3  /

1 row created.

SQL> 

Вот вложенная таблица:

SQL> create type school_child_t as object(
  2      cid ref child_t,
  3      sid ref school_t)
  4  /

Type created.

SQL> create table school_child_tab of school_child_t
  2  /

Table created.

SQL>

Заполняем таблицу пересечений следующим образом:

SQL> insert into school_child_tab
  2        select cid, sid
  3        from
  4          ( select ref(c) as cid from child_tab c where c.cid = 111 )
  5          , ( select ref(s) as sid from school_tab s where s.sid = 222 )
  6  /

1 row created.

SQL> insert into school_child_tab
  2        select cid, sid
  3        from
  4          ( select ref(c) as cid from child_tab c where c.cid = 112 )
  5          , ( select ref(s) as sid from school_tab s where s.sid = 222 )
  6  /

1 row created.

SQL> insert into school_child_tab
  2        select cid, sid
  3        from
  4          ( select ref(c) as cid from child_tab c where c.cid = 113 )
  5          , ( select ref(s) as sid from school_tab s where s.sid = 222 )
  6  /

1 row created.

SQL> insert into school_child_tab
  2        select cid, sid
  3        from
  4          ( select ref(c) as cid from child_tab c where c.cid = 113 )
  5          , ( select ref(s) as sid from school_tab s where s.sid = 223 )
  6  /

1 row created.

SQL>

Запрос результатов

SQL> select c.name as child_name
  2         , s.name as school_name
  3  from     school_child_tab sc
  4              join child_tab c
  5                  on ( ref(c) = sc.cid )
  6              join school_tab s
  7                  on ( ref(s) = sc.sid )
  8  /

CHILD_NAME           SCHOOL_NAME
-------------------- --------------------
Fred                 Bash Street
Ayesha               Bash Street
Aadil                Greyfriars
Aadil                Bash Street

SQL>

Конечно, возникает вопрос: если вы собираетесь использовать REF объекта, вам нужен столбец идентификатора? Конечно, я думаю, что вводить в заблуждение наличие атрибута с именем CID типа NUMBER для типа CHILD_T и атрибута с тем же именем, но с типом данных REF для типа SCHOOL_CHILD_T.

...