Ich habe folgendes Problem, vielleicht könnt ihr mir helfen:
Ich habe eine Tabelle in der sogenannte Ontologie-Begriffe gespeichert sind, die aus verschiedenen Namensräumen kommen können (GO/ECO und andere).
Ontology:
-----------
Sie haben alle dieselbe Form weshalb es meines Erachtens nach sinnvoll ist, sie alle in eine Tabelle zu schreiben. Allerdings erschwert mir das, die klare Definition von Fremdschlüsselbeziehungen.Code:ID Kurzname Namensraum Beschreibung ECO:0000001 ECO evidence_code inferred by curator ECO:0000004 ECO evidence_code inferred from cell fractionation GO:0000006 GO molecular_function high affinity zinc uptake transmembrane transporter activity GO:0000007 GO molecular_function low-affinity zinc ion transmembrane transporter activity GO:0005737 GO cellular_component cytoplasm GO:0005783 GO cellular_component endoplasmic reticulum
Stellen wir uns eine weitere Tabelle vor, die auf einen ganz bestimmten Namensraum von diesen Ontologie-IDs mit Fremdschlüssel verweisen soll. Zum Beispiel eine Tabelle die Kompenenten mit Lokalisierungsinformationen verknüpft. (für die biologisch-bewanderten unter Euch: in welchem compartment, tissue, taxon befindet sich ein bestimmtes Protein)
Tabelle Lokalisation
---------------------
Was ich jetzt natürlich möchte ist das diese Spalte Compartment einerseits auf die Spalte ID aus meiner oberen Tabelle verweist, aber natürlich nicht auf die Namensräume "evidence_code" und "molecular_function".Code:Protein Compartment Alkoholdehydrogenase GO:0005737
Kann ich in irgendeinerweise einen Check Constraint setzen ? Oder wie müsste die Fremdschlüsseldefintion aussehen damit ich nur die "spezielle Teilmenge" aus Tabelle "Ontology" als zulässige IDs für Tabelle "Lokalisation" zulasse.
Ich hoffe ich konnte einigermaßen rüberbringen, was ich meine.
Vielen Dank schonmal für Eure Antworten
Micha
PS: Ich benutze PostgreSQL 8.4.1
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
mal so als Spielerei ...Code:test=# select * from onko ; id | namensraum ------------+-------------------- GO:0000006 | molecular_function GO:0005737 | cellular_component (2 rows) test=*# select * from lokalisation ; protein | compartment ---------+------------- (0 rows) test=*# create or replace function check_onko() returns trigger as $$begin perform * from onko where id=new.compartment and namensraum='cellular_component'; if found then return new; else raiseexception 'das geht so ned'; end if; end;$$ language plpgsql; CREATE FUNCTION test=*# create trigger trg1 before insert on lokalisation for each row execute procedure check_onko(); CREATE TRIGGER test=*# insert into lokalisation values ('Alkoholdehydrogenase','GO:0005737'); INSERT 0 1 test=*# insert into lokalisation values ('irgend was','GO:0000006'); ERROR: das geht so ned test=!#
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Ich habe auf den meisten Tabellen schon einen After-Trigger weil ich so eine Art Protokoll-Tabellen habe, wo ich nach jeder Einfügeoperation die ursprünglichen Werte nochmal sichere.
Meines Wissens wäre diese Art von Test ja ein Before Trigger, da ich ja nicht möchte das etwas eingefügt wird, wenn die Bedingung verletzt ist.
Meines Wissens nach ist es möglich sowohl einen Before als auch einen After Trigger pro Tabelle zu definieren. Könntest du mir ansatzweise zeigen, wie so ein Before Trigger aussehen müsste. Oder mich auf eine geeignete Seite verweisen wo ich fündig werde ?
was genau müsste in den Body meiner Funktion (SP)? oder kann ich das ganze schon direkt im Trigger abhandeln ?Code:CREATE TRIGGER tr_check_namespace Before INSERT OR UPDATE OR DELETE ON "localisation" FOR EACH ROW EXECUTE PROCEDURE sp_check_namespace();
So ähnlich sieht mein After Trigger aus
Code:CREATE OR REPLACE FUNCTION sp_check_namespace() RETURNS trigger AS $BODY$ BEGIN .... END; $BODY$ LANGUAGE PLpgSQL CALLED ON NULL INPUT VOLATILE EXTERNAL SECURITY INVOKER;
ui du warst schneller, mom ich schau mir kurz dein Beispiel an
EDIT:
-----------
AH super, habs noch nit getestet, aber dein Beispiel ist super, glaube damit kriege ich das hin! Danke für die schnelle Antwort. Ich meld mich nochmal wenn es funzt![]()
Nicht ganz korrekt, du kannst beliebig viele definieren. Sie feuern in alphabetischer Reihenfolge.
Guggst Du anderes Posting von mir.Könntest du mir ansatzweise zeigen, wie so ein Before Trigger aussehen müsste. Oder mich auf eine geeignete Seite verweisen wo ich fündig werde ?
Beim Delete brauchst das wohl nicht zu prüfen ...was genau müsste in den Body meiner Funktion (SP)? oder kann ich das ganze schon direkt im Trigger abhandeln ?Code:CREATE TRIGGER tr_check_namespace Before INSERT OR UPDATE OR DELETE ON "localisation" FOR EACH ROW EXECUTE PROCEDURE sp_check_namespace();
Andreas
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
was genau bedeutet "perform *" ?create or replace function import.check_compartment() returns trigger as $$begin perform * from term where identifier=new.identifier and namespace='cellular_component'; if found then return new; else raiseexception 'You have to provide a correct cellular component identifier i.e. ECO:0000004'; end if; end;$$ language plpgsql;
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Ich hatte nach "perform postgres" gegoogelt, aber scheinbar den ersten Treffer gleich übersehen.
Aus irgendeinem Grund bekomme ich folgenden Fehler, wenn ich deine Funktion leicht abgeändert versuche zu implementieren:
Okay hat sich erledigt, hab nach raiseexception gegoogelt und herausgefunden, dass es auseinander geschrieben werden mussCode:testdb=# create or replace function check_compartment() returns trigger as $$begin perform * from term where identifier=new.identifier and namespace='cellular_component'; if found then return new; else raiseexception 'You have to provide a correct cellular component identifier'; end if; end;$$ language plpgsql; ERROR: syntax error at or near "raiseexception" LINE 1: raiseexception 'You have to provide a correct cellular compo... ^ QUERY: raiseexception 'You have to provide a correct cellular component identifier' CONTEXT: SQL statement in PL/PgSQL function "check_compartment" near line 1 testdb=#Sorry für meine voreilige Rückmeldung O.o Jetzt hats geklappt.
Geändert von mweasty (08.12.2009 um 16:12 Uhr)
--
https://www.xing.com/profile/Andreas_Kretschmer7ads Das hatte dir akretschmer gestern schon gesagt und siehe da sobald du das machst, funktioniert es ;-)
Links: Tobias Bauer - IT- und Funkdienstleistungen - Bilderrahmen-kaufen.de - Der Onlineshop für Bilderrahmen & Fotorahmen - Funkforum
Lesezeichen