1. Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm
    Information ausblenden

Speichern einer Baumstruktur mit parent column und unique constraint

Dieses Thema im Forum "DB2" wurde erstellt von smirk_mirkin, 26 September 2014.

  1. smirk_mirkin

    smirk_mirkin Benutzer

    Hallo,

    ich möchte mit Hibernate einen Baum in eine Tabelle speichern.
    Genutzt wird dazu eine Spalte parent, die den Vaterknoten speichert.
    Hier das CREATE-Statement:
    Code:
    CREATE TABLE KATEGORIE (
        ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1),
        BEZEICHNUNG VARCHAR(100) NOT NULL,
        OBERKATEGORIE INTEGER NOT NULL,
        INDEX INTEGER,
        PRIMARY KEY (ID),
        CONSTRAINT uc_KATEGORIE UNIQUE (BEZEICHNUNG, OBERKATEGORIE)
    );
    Nun darf wegen dem unique constraint kein parent null sein, was aber bei der Wurzel der Fall ist. Erschwerend kommt hinzu, dass Hibernate automatisch aus parent einen foreign key macht, also kann ich auch nicht einfach irgendeinen parent bei der Wurzel setzen. Das Constraint brauch ich übrigens, da sonst beim zweimaligen Einlesen derselben Daten auch alles zweimal abgespeichert wird.

    Wie könnte man das Dilemma am saubersten Lösen bzw. kann man vllt irgendwie Hibernate untersagen, den Fremdschlüssel auf parent zu erstellen?
     
  2. ukulele

    ukulele Datenbank-Guru

    Ohne mich mit DB2 jemals befasst zu haben, was wäre denn mit parent_id = id, also beides auf 1 beim Wurzeleintrag.
     
  3. smirk_mirkin

    smirk_mirkin Benutzer

    Also sobald der Fremdschlüssel draufliegt, was bei der Ausführung meines Hibernate-Programms passiert, geht das nicht mehr.

    Davor würde es rein theoretisch gehen, aber dann müsste ich einen Datensatz manuell einfügen und das wäre doch recht unsauber. Besser wäre, den Fremdschlüssel irgendwie zu verhindern. Aber dafür kenn ich mich zu wenig mit Hibernate aus.
     
  4. ukulele

    ukulele Datenbank-Guru

    Nun man könnte auch bei der Erstellung der Tabelle schon einen Wurzeleintrag erstellen und den Fremdschlüssel erst im Anschluss. Irgendwie wird man sich behelfen müssen, aber vieleicht gibt es hier noch jemanden der sowas schonmal hatte. Dein Fall ist aber schon speziell :)
     
  5. smirk_mirkin

    smirk_mirkin Benutzer

    Ja man könnte die Wurzel halt schon bei Createn erstellen, ist aber halt unsauber. Aber ne wirklich saubere Lösung scheint es nicht zu geben. Ich frage mich halt auch, warum bei dem unique constraint nicht wenigstens ein Wert null sein darf.

    So speziell kann das Problem ja gar nicht sein, man wird ja öfters mal einen Baum mit nicht eindeutigen Namen einlesen wollen? :D Man sieht ja schon an meinem Code oben, dass es sich um einen Kategorienbaum in einem online-Shop handelt.

    Mir kam auch gerade noch ne Idee:
    Man könnte natürlich auch das unique constraint rausnehmen und in der Einlese-Anwendung erst mal nen fetten Select machen und den mit den einzulesenden Daten abgleichen. Und dann nur noch die inserten, die eben noch fehlen. Dann hätte man aber die Konsistenz nicht auf der Datenbank gesichert, sondern nur in der Anwendung.
     
  6. akretschmer

    akretschmer Datenbank-Guru

    In Deiner Tabelle sehe ich keine Spalte parent.

    Code:
    test=*# create table bla (id int primary key, parent int references bla, val text);
    CREATE TABLE
    Time: 207,389 ms
    test=*# \d bla
      Table "public.bla"
     Column |  Type  | Modifiers
    --------+---------+-----------
     id  | integer | not null
     parent | integer |
     val  | text  |
    Indexes:
      "bla_pkey" PRIMARY KEY, btree (id)
    Foreign-key constraints:
      "bla_parent_fkey" FOREIGN KEY (parent) REFERENCES bla(id)
    Referenced by:
      TABLE "bla" CONSTRAINT "bla_parent_fkey" FOREIGN KEY (parent) REFERENCES bla(id)
    
    Wqarum sollte sowas wie gezeigt nicht gehen? Und warum darf ein unique nicht NULL sein?

    Code:
    test=*# drop table bla;
    DROP TABLE
    Time: 27,295 ms
    test=*# create table bla(i int unique);
    CREATE TABLE
    Time: 5,078 ms
    test=*# insert into bla values (1);
    INSERT 0 1
    Time: 0,444 ms
    test=*# insert into bla values (null);
    INSERT 0 1
    Time: 0,203 ms
    test=*# insert into bla values (null);
    INSERT 0 1
    Time: 0,194 ms
    test=*# insert into bla values (null);
    INSERT 0 1
    Time: 0,164 ms
    test=*# insert into bla values (1);
    ERROR:  duplicate key value violates unique constraint "bla_i_key"
    DETAIL:  Key (i)=(1) already exists.
    Time: 0,351 ms
    
    Sollte auch mit DB/Halbe gehen.
     
  7. smirk_mirkin

    smirk_mirkin Benutzer

    Naja parent ist OBERKATEGORIE im Codebeispiel.

    Das was du zeigst geht, aber du hast kein unique constraint erstellt. Ich schließe per uc aus, dass ein title-parent-Paar doppelt vorkommt.
    Code:
    CONSTRAINT uc_KATEGORIE UNIQUE (BEZEICHNUNG, OBERKATEGORIE)
    Bei DB2 müssen alle von diesem Constraint berührten
    Attribute not null sein, keine Ahnung wieso.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden