Genau, und das ist auch richtig so, oder? Vielleicht sollten wir zunächst klarstellen, ob das ERM sowie die psql DB so korrekt angelegt sind?! Ich hoffe doch das ist der Fall?
Genau und ich stehe jetzt vor dem Problem wie ich die Daten in die DB einfüge, sofern die DB so überhaupt richtig ist. Geht das mit case Ausdrücken oder wie stellt man das in der Regel an eine solche DB mit Daten zu befüllen?Damit kannst Du nur Werte für fk_person_id in der Tabelle rel_person_artikel eintragen, für die vorher in der Tabelle person ein Eintrag mit der gleichen person_id gemacht wurde.
Andreas
Danke!
Auf den ersten Blick schaut es gut aus, also die Tabellenstruktur.
Nun, man füllt zuerst die Tabellen, auf die später referenziert wird. Oder man stellt die Constraints deferred. Damit kann ich auch erst einmal Daten in die Tabelle mit dem FK eingeben:Genau und ich stehe jetzt vor dem Problem wie ich die Daten in die DB einfüge, sofern die DB so überhaupt richtig ist. Geht das mit case Ausdrücken oder wie stellt man das in der Regel an eine solche DB mit Daten zu befüllen?
Danke!
Oder man wartet auf Release 9.1, welche dann hoffentlich writeable CTE drin hat. Dann kannst Du viele Tabellen mit einem einzigen Insert befüllen:Code:test=# create table master (id serial primary key ); NOTICE: CREATE TABLE will create implicit sequence "master_id_seq" for serial column "master.id" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "master_pkey" for table "master" CREATE TABLE test=*# create table slave (master_id int references master deferrable initially deferred); CREATE TABLE test=*# insert into slave values(1); INSERT 0 1
my blog: writeable CTE - a short performance test
Leider kommt das nicht schon in 9.0, sehr sehr schade...
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Ok, das heißt in meinem Fall, ich fülle zunächst die "Nichtrelationstabellen" artikel, ausgabe, keywords, person und zeitschrift.
Das hat soweit alles geklappt, knapp 9000 Artikel sind jetzt in der Datenbank. Und jetzt weiß ich nicht weiter. Wie stelle ich jetzt die Referenzen her?
Bspw. muss der Tabelle artikel die ausgabe_id der Tabelle ausgabe als FK hinzugefügt werden, der Tabelle ausgabe die zeitschrift_id der Tabelle zeitschrift etc.
Bei der Tabelle rel_person_artikel muss die person_id und die artikel_id verknüpft eingefügt werden.
Das ist jetzt für mein Hirn nicht mehr ganz so trivial
Wie muss ich vorgehen?
Ahhh, nun weiß ich erst einmal, wo Dein Problem ist.
Nun, der Weg ist eigentlich wie folgt:
- Insert in die Haupttabelle. Dabei wird ein neuer Wert für die SERIAL-Spalte generiert.
- Dann Eingabe der Detaildaten. Dazu nutzt man die Funktion currval(), um an den Wert der Sequence zu gelangen.
Kurzdemo:
Du könntest Dir auch den Link von mir ansehen, da habe ich mittels plpgsql-Script einige tausend Datensätze in ein solches Schema eingefügt.Code:test=# create table master (id serial primary key, name text); NOTICE: CREATE TABLE will create implicit sequence "master_id_seq" for serial column "master.id" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "master_pkey" for table "master" CREATE TABLE test=*# create table detail (id_master int references master, detail int); CREATE TABLE test=*# insert into master (name) values ('Andreas'); INSERT 0 1 test=*# insert into detail (id_master, detail) values (currval('master_id_seq'), 10); INSERT 0 1 test=*# select * from master; id | name ----+--------- 1 | Andreas (1 row) test=*# select * from detail ; id_master | detail -----------+-------- 1 | 10 (1 row)
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Statt currval() könnte man auch INSERT ... RETURNING nutzen.
Xandrian: Kurz gesagt: Du hast ein falsches Konzept und willst nicht auf ads hören
Jetzt NEU: PostgreSQL - Datenbankpraxis für Anwender, Administratoren und Entwickler
PostgreSQL Service & Support
Danke, das hat mir jetzt sehr geholfen - nun hab ich das Konzept verstanden. Und das ist also die Standard-Herangehensweise beim Referenzieren von Tabellen?
Ich habe das ganze für einen Datensatz (meiner 9000) durchgeführt und es hat geklappt, INNER JOINS funktionieren einwandfrei. Um sicherzustellen, dass meine Vorgehensweise korrekt war hier ein Codebeispiel:
usw. bis man alle Tabellen durch hat.Code:-- Referenzierung der Tabellen zeitschrift, ausgabe und artikel INSERT INTO zeitschrift (name,kurzname,issn) VALUES ('Journal B','JB','0000-1111'); INSERT INTO ausgabe (fk_zeitschrift_id,heft_nr,jahr,jahrgang) VALUES (currval('zeitschrift_zeitschrift_id_seq'),'12','1989','4'); INSERT INTO artikel (fk_ausgabe_id,dok_nr,titel,inhalt,anfangsseite,endseite,erfassungsdatum,korrekturdatum) VALUES (currval('ausgabe_ausgabe_id_seq'),'1','Ein Titel','Ein Inhalt','22','28','1980-12-12','1981-04-12');
Jetzt stellt sich mir natürlich die Frage was passiert wenn der Datensatz mit der keyword_id=1 das keyword='Heuchler' und 100 Datensätze später kommt der Datensatz keyword_id=101 der auch das keyword='Heuchler' hat? Oder bei Personen, die mehrmals vorkommen, da sie mehrere Artikel verfasst haben?
Wie geht man hier vor?
Gruß
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Etwas bescheiden formuliert, sorry. Also:
Dieses currval()-Konzept setzt ja voraus, dass jeder Datensatz einzeln eingepflegt werden muss, denn der Wert der Sequenz (der currrent value) darf sich beim Einfügen des Datensatzes ja nicht ändern.
Das führte nun zu der Frage was passiert wenn folgendes eintritt.
Ich habe 9000 Datensätze. Da kann es ja durchaus vorkommen, dass ein Keyword z.B. das Keyword "Heuchler" in mehreren Datensätzen vorkommt.
Bspw. in Datensatz 1:
keyword_id=1
keyword='Heuchler'
und später in Datensatz 400:
keyword_id=400
keyword='Heuchler'
Das wäre ja nicht im Sinne des Erfinders wenn das so in der Tabelle keywords stehen würde, richtig?
Hoffe du hast meine Frage verstanden!
Ja.
Dann fragt man die ID halt ab:
AndreasCode:test=*# create table master (id serial primary key, name text); NOTICE: CREATE TABLE will create implicit sequence "master_id_seq" for serial column "master.id" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "master_pkey" for table "master" CREATE TABLE Time: 4.693 ms test=*# create table slave (id_master int references master, name text); CREATE TABLE Time: 5.796 ms test=*# insert into master (id, name) values (default, 'master1'); INSERT 0 1 Time: 0.805 ms test=*# insert into master (id, name) values (default, 'master2'); INSERT 0 1 Time: 0.317 ms test=*# insert into master (id, name) values (default, 'master3'); INSERT 0 1 Time: 0.299 ms test=*# insert into slave (id_master, name) values((select id from master where name ='master1'), 'slave1'); INSERT 0 1 Time: 0.800 ms test=*# insert into slave (id_master, name) values((select id from master where name ='master3'), 'slave3'); INSERT 0 1 Time: 0.419 ms test=*# insert into slave (id_master, name) values((select id from master where name ='master1'), 'slave1'); INSERT 0 1 Time: 0.466 ms test=*# test=*# select * from master; id | name ----+--------- 1 | master1 2 | master2 3 | master3 (3 rows) Time: 0.276 ms test=*# select * from slave; id_master | name -----------+-------- 1 | slave1 3 | slave3 1 | slave1 (3 rows)
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Also mir ist schon klar, was du machst allerdings kann ich dein Beispiel nicht auf mein Problem übertragen.
Angenommen das erste Dokument, das ich in meine DB schreibe hat 3 Keywords (Heuchler,Affe,Hund). Sie bekommen die keyword_ids 1,2 und 3.
Dann würden meine Statement so aussehen (korrigiere mich wenn ich falsch liege):
Jetzt füge ich das zweite Dokument in die DB ein:Code:INSERT INTO keywords (keywords) VALUES ('Heuchler'); INSERT INTO rel_keywords_artikel (fk_artikel_id, fk_keywords_id) VALUES (currval('artikel_artikel_id_seq'), currval('keywords_keywords_id_seq')); INSERT INTO keywords (keywords) VALUES ('Affe'); INSERT INTO rel_keywords_artikel (fk_artikel_id, fk_keywords_id) VALUES (currval('artikel_artikel_id_seq'), currval('keywords_keywords_id_seq')); INSERT INTO keywords (keywords) VALUES ('Hund'); INSERT INTO rel_keywords_artikel (fk_artikel_id, fk_keywords_id) VALUES (currval('artikel_artikel_id_seq'), currval('keywords_keywords_id_seq'));
Affe käme zum zweiten Mal vor und hätte unterschiedliche IDs. Um das zu verhindern muss ich ja überprüfen, ob der Wert schon in der Tabelle keyword vorhanden ist. Dazu muss ich doch aber den currval() überprüfen, den ich gerade eintrage?Code:INSERT INTO keywords (keywords) VALUES ('Stadt'); INSERT INTO rel_keywords_artikel (fk_artikel_id, fk_keywords_id) VALUES (currval('artikel_artikel_id_seq'), currval('keywords_keywords_id_seq')); INSERT INTO keywords (keywords) VALUES ('Affe'); INSERT INTO rel_keywords_artikel (fk_artikel_id, fk_keywords_id) VALUES (currval('artikel_artikel_id_seq'), currval('keywords_keywords_id_seq'));
Wie sähe das in meinem konkreten Beispiel aus?
Danke! Gruß
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen