sql >> Database >  >> RDS >> Oracle

Rails-model met externe sleutel naar zichzelf

Het probleem is dus dat er een gebruiker bovenaan de hiërarchie moet staan, een gebruiker voor wie er geen manager is (editor in uw voorbeeld). Dat is de reden waarom de klassieke oplossing voor dit soort structuur is om null-waarden toe te staan. U erkent dit in uw slotparagraaf:

De kicker is dat als de eerste gebruiker geen CREATOR of EDITOR heeft, er geen "tijdelijke" is:je moet de verplichte beperking weggooien. Als u dit doet, zal het probleem met de recursieve externe sleutelbeperking verdwijnen.

Het alternatief is om te introduceren wat Aristoteles een Prime Mover noemde, een Gebruiker wiens Schepper hijzelf is. Gezien deze tabel:

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)
)
/

het is vrij eenvoudig om zo'n gebruiker aan te maken:

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

1 row created.

SQL> commit;

Commit complete.

SQL>

Dus waarom is dit niet de canonieke oplossing. Welnu, het leidt tot een enigszins maf gegevensmodel dat verwoesting kan veroorzaken met hiërarchische zoekopdrachten zodra we een paar extra gebruikers hebben toegevoegd.

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> 

Eigenlijk houdt de database er niet van dat USERID zijn eigen editor is. Er is echter een tijdelijke oplossing, namelijk de NOCYCLE trefwoord (geïntroduceerd met 10g). Dit vertelt de database om kringverwijzingen in de hiërarchie te negeren:

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>

Hier maakt het niet uit omdat de gegevens nog steeds correct hiërarchisch zijn. Maar wat gebeurt er als we dit doen:

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

1 row updated.

SQL> 

We verliezen een relatie ( 1 -> 7). We kunnen de CONNECT_BY_ISNOCYCLE pseudo-kolom gebruiken om te zien welke rij aan het fietsen is.

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 heeft veel extra functionaliteit om het werken met hiërarchische gegevens in pure SQL gemakkelijker te maken. Het staat allemaal in de documentatie. Meer informatie .



  1. MySQL IN met LIKE

  2. Dichtstbijzijnde record voor een reeks datums

  3. Hoe gebruik ik de Postgresql ANY-operator in een NOT IN-statement?

  4. mysql_connect():Er kon geen verbinding worden gemaakt omdat de doelmachine dit actief weigerde