Oracle
 sql >> база данни >  >> RDS >> Oracle

Rails модел с външен ключ към себе си

Така че проблемът е, че трябва да има потребител на върха на йерархията, потребител, за когото няма мениджър (редактор във вашия пример). Ето защо класическото решение за този вид структура е да се разрешат нулеви стойности. Вие потвърждавате това в заключителния си параграф:

Най-важното е, че ако първият потребител няма СЪЗДАТЕЛ или РЕДАКТОР, тогава няма "временно":трябва да се откажете от задължителното ограничение. Ако направите това, проблемът с ограничението на рекурсивния външен ключ ще изчезне.

Алтернативата е да се въведе това, което Аристотел нарича Първичен двигател, потребител, чийто Създател е самият той. При тази таблица:

create table t72
( userid number not null
  , creator number not null
  , editor number not null
  , constraint t72_pk primary key (userid)
  , constraint t72_cr_fk foreign key (creator) 
                references t72 (userid)
  , constraint t72_ed_fk foreign key (editor) 
                references t72 (userid)
)
/

доста лесно е да създадете такъв потребител:

SQL> insert into t72 values (1,1,1)
  2  /

1 row created.

SQL> commit;

Commit complete.

SQL>

Така че защо това не е каноничното решение. Е, това води до малко шантав модел на данни, който може да създаде хаос с йерархичните заявки, след като добавим още няколко потребители.

SQL> select lpad(' ', level-1)|| u.userid as userid
  2          , u.name
  3          , u.editor
  4  from t72 u
  5  connect by
  6     prior userid = editor
  7  start with userid=1
  8  /
ERROR:
ORA-01436: CONNECT BY loop in user data



no rows selected

SQL> 

По принцип базата данни не харесва USERID да е неин собствен редактор. Въпреки това има заобиколно решение, което е NOCYCLE ключова дума (въведена с 10g). Това казва на базата данни да игнорира кръговите препратки в йерархията:

SQL> select lpad(' ', level-1)|| u.userid as userid
  2          , u.name
  3          , u.editor
  4  from t72 u
  5  connect by nocycle
  6     prior userid = editor
  7  start with userid=1
  8  /

USERID     NAME           EDITOR
---------- ---------- ----------
1          ONE                 1
 2         TWO                 1
  3        THREE               2
  4        FOUR                2
  5        FIVE                2
  6        SIX                 2
   7       SEVEN               6

7 rows selected.

SQL>

Тук няма значение, защото данните все още са правилно йерархични. Но какво се случва, ако направим това:

SQL> update t72 set editor = 7
  2  where userid = 1
  3  /

1 row updated.

SQL> 

Губим връзка ( 1 -> 7). Можем да използваме псевдо-колоната CONNECT_BY_ISNOCYCLE, за да видим кой ред се движи.

SQL> select lpad(' ', level-1)|| u.userid as userid
  2          , u.name
  3          , u.editor
  4          , connect_by_iscycle
  5  from t72 u
  6  connect by nocycle
  7     prior userid = editor
  8  start with userid=1
  9  /

USERID     NAME           EDITOR CONNECT_BY_ISCYCLE
---------- ---------- ---------- ------------------
1          ONE                 7                  0
 2         TWO                 1                  0
  3        THREE               2                  0
  4        FOUR                2                  0
  5        FIVE                2                  0
  6        SIX                 2                  0
   7       SEVEN               6                  1

7 rows selected.

SQL>  

Oracle има много допълнителни функции, за да улесни работата с йерархични данни в чист SQL. Всичко е в документацията. Научете повече .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Oracle ODP.Net с Entity Framework 6 - Доставчик, съвместим с база данни за Entity Framework, не можа да бъде намерен

  2. SUBSTR и INSTR SQL Oracle

  3. Най-добри практики:Задачи за поддръжка и подобряване на Oracle Cloud

  4. Групиране на SQL резултати по месеци

  5. ODP.NET подлежи ли на разпространение?