Foreign Key mittels der contains-abfrage?

Kampfgummibaerlie

Datenbank-Guru
Beiträge
731
Mein anliegen wäre jetzt, dass ich möchte, dass sich die lower(mietzeit) von meiner Tabelle Vermietungen in der in der Tabelle Öffnungszeiten enthaltenen Timerange/s liegt.

Muss ich mir da einen Foreign Key einbauen? Oder doch eine Check Constraint, die ich bisher versucht habe, er aber am Ende meinte "missing from ..."

Wäre wie immer sehr dankbar über das erreichen von mehr Wissen über das Ganze ;)

Beispiel:
Öffnungszeit(Montag) von 14:00 bis 18:00

Ich möchte jetzt mittels einem Check Constraint oder Foreign Key irgendwie lösen, damit kein Startwert der vor 14:00 bzw. nach 18:00 eintragbar ist. Die Upper(tsrange) lassen wir ersteinmal, weil Mutter nichts dagegen hat, wenn sie ein wenig länger durt bleibt, solange der Kunde vor 18:00, oder wann sie auch immer an dem Tag zusperrt, dort ist.

Wäre euch natürlich, wie immer, sehr dankbar ;D

Da ich ja nicht allzuviel "Traffik" saugen möchte, würde ich das eben gerne über einen Constraint oder Foreign Key machen, und nicht zwangshaft über die Kombinierung von endlos vielen Funktionen.

Anbei, fällt mir ein, jetzt am Ende, ist das über eine/mehrere Trigger Procedure/s möglich? (Ja, ich werde auch selbst ein wenig nachdenken darüber ;) )
 
Werbung:
Mein anliegen wäre jetzt, dass ich möchte, dass sich die lower(mietzeit) von meiner Tabelle Vermietungen in der in der Tabelle Öffnungszeiten enthaltenen Timerange/s liegt.

Muss ich mir da einen Foreign Key einbauen? Oder doch eine Check Constraint, die ich bisher versucht habe, er aber am Ende meinte "missing from ..."

Ranges können nicht als Foreign Keys verwended werden, auch mit einem Check Constraint wirst das nicht hinbekommen. Ein TRIGGER sollte aber gehen.
 
Darf ich wieder um ein wenig Hilfe bitten?
Spiele mich schon eine Weile dabei, eine "einfachere" Methode mal zu lösen.:

Code:
create or replace function valueint() returns trigger as $$
begin
if new.two.id > max(one.id) from one, two
then raise exception 'Sorry';
end if;
return new;
end;
$$ language plpgsql;

wo wäre die from-klausel richtig? bzw. wie würde diese trigger-procedure richtig?
ich habe eine tabelle one, mit einer spalte id als integer
ich habe eine tabelle two, mit einer spalte id als integer
ich will checken, dass, wenn ich einen wert in table 2 eingebe, der wert größer ist, als der größte wert der tabelle one.

Errormeldung sieht so aus:
ERROR: invalid reference to FROM-clause entry for table "two" LINE 1: SELECT new.two.id > max(one.id) from one, two

Danke, wie immer :)
 
vereinfacht, aber ich denke, damit kommst Du weiter:

Code:
test=*# create table oeffnungszeiten(tag int, von_bin int4range);
CREATE TABLE
test=# insert into oeffnungszeiten values (1, '(10,18]');
INSERT 0 1
test=*# create table ausleihe (tag int, von_bis int4range);
CREATE TABLE
test=*# create or replace function check_ausleihe() returns trigger as $$begin if (select count(1) from oeffnungszeiten where tag = new.tag and von_bis @> new.von_bis) then return new; else raise exception 'sorry'; end if; end;$$language plpgsql;
CREATE FUNCTION
test=*#
test=*#
test=*# create trigger check_trigger before insert on ausleihe for each row execute procedure check_ausleihe();
CREATE TRIGGER
test=*#
test=*#
test=*# insert into ausleihe values (1, '[12,16)');
INSERT 0 1
test=*# select * from ausleihe ;
 tag | von_bis
-----+---------
  1 | [12,16)
(1 row)

test=*# insert into ausleihe values (1, '[8,20)');
FEHLER:  sorry
test=*#
 
Code:
begin
if (
  select lower(oeffnungszeit) from oeffnungszeiten, vermietungen
   where oeffnungszeiten.wochentag_id
     = wochentag_datum(lower(new.mietzeit)::date) and
  lower(mietzeit)::time > lower(oeffnungszeit)
) then return new; else raise exception 'sorry'; end if;
end;

Trigger muss ich deutlich üben ^^

Folgendes Problem:
er gibt den Error "Sorry" zurück, obwohl er eigentlich gerade offen haben sollte?

Gehe ich jetzt zu schnell ins Thema? Ifs wäre das Thema, mit dem ich mich befassen müsste. Trigger sind mir ja schonmal gelungen.
 
vereinfacht, aber ich denke, damit kommst Du weiter:

Code:
test=*# create table oeffnungszeiten(tag int, von_bin int4range);
CREATE TABLE
test=# insert into oeffnungszeiten values (1, '(10,18]');
INSERT 0 1
test=*# create table ausleihe (tag int, von_bis int4range);
CREATE TABLE
test=*# create or replace function check_ausleihe() returns trigger as $$begin if (select count(1) from oeffnungszeiten where tag = new.tag and von_bis @> new.von_bis) then return new; else raise exception 'sorry'; end if; end;$$language plpgsql;
CREATE FUNCTION
test=*#
test=*#
test=*# create trigger check_trigger before insert on ausleihe for each row execute procedure check_ausleihe();
CREATE TRIGGER
test=*#
test=*#
test=*# insert into ausleihe values (1, '[12,16)');
INSERT 0 1
test=*# select * from ausleihe ;
tag | von_bis
-----+---------
  1 | [12,16)
(1 row)

test=*# insert into ausleihe values (1, '[8,20)');
FEHLER:  sorry
test=*#

War vorher bei Eltern im Haus, und konnte es nur überfliegen. Bin wieder zuhause, werde später dann noch Abendessen, aber um deine Syntax/e(?) zu korrigieren:

Gleich im 1. create table-Syntax ist ein Fehler, auf den ich nur für alle anderen hinweise:
Es sollte statt dem von_bin ein von_bis drinnen stehen ;)

Und ja, herr Elefant, Fehler sind Menschlich ;)

EDIT 2:
Beim bissl herumbasteln und in der Praxis anwenden funktioniert das Prinzip exakt so, wie ich es gerne hätte, nur habe ich dabei einen Gedanken, der womöglich nicht damit funktionieren würde, weil Mutter ja doch öfters, für eher ... reife Personen, die nicht allzuschnell sind, ein paar Minuten länger offen hat. entsprechend würde ich versuchen, nur den Anfangszeitpunkt zu kontrollieren, dass er innerhalb der Öffnungszeit liegt, der "Bis-Wert" kann ja x-beliebig sein.

Aber ja, ich hoffe, dass das alles noch was wird :D
 
Zuletzt bearbeitet:
Code:
create function nut() returns trigger as $$
begin
if (table2.int @> table1.pos_int) then return new; else raise exception 'sorry'; end if;
end;$$
language plpgsql;

ist die Function, habe auch einen Trigger gebaut für table2, die for each row die oben gegebene function executed, jedoch bekomme ich folgenden error:

ERROR: error CONTEXT: PL/pgSQL function nut() line 3 at RAISE SQL-Status: P0001

Warum ich nicht einfach mr. Elephants Lösung nehme?
Weil ich das Thema verstehen möchte ^^
 
werde mich mit funktionen beschäftigen, die einen boolean value returnen.
weil man dort offenbar IMMER eine if-klausel einbauen muss, damit sie boolean returnen können.

hier eine nette (kleine) Funktion :D
Code:
create function positiv(x integer) returns boolean as 'begin if x > 0 then return true; else return false; end if; end;' language plpgsql;

EDIT: Zur Erklärung: sie sagt "true", falls der Parameter über 0 ist, anderenfalls eben "false".
 
*im Kreis renn*

Ich habe es endlich geschafft xD
Ich glaube es lag am falschen Textverständniss von mir.

Ich habe einen Trigger erstellt, der sich nicht before auslöst, sondern eben einen, der sich erst nach dem insert "zündet".
Anbei habe ich das Ganze auch ein wenig anders verwendet, und die Int4Range auf tsrange, und was weiß ich was alles gemacht :)

Danke, kann ich schlafen gehen ! :D
 
heute morgen funktionierts irgendwie nicht, ...

Folgender Code steht (jetzt) in meiner Trigger Procedure:
Code:
 begin if (select wochentag_datum(lower(orders.ordertime)::date) = openings.weekday and openings.opening @> lower(ordertime)::time from orders, openings) 
then return new; else raise exception 'Nicht möglich'; end if; end;

Er gibt mir jedoch immer den Error aus, selbst wenn in openings ein weekday steht, welcher wiederum dem wochentag vom datum der "Startzeit" ist.
 
Werbung:
Habe mir eine halbwegs funktionierende "gebaut":

Code:
 begin if (select count(1) from oeffnungszeiten
where wochentag_id = wochentag_datum(lower(new.mietzeit)::date) and oeffnungszeiten.oeffnungszeit::timerange @> lower(new.mietzeit)::time) then return new; else raise exception 'sorry'; end if; end;

Scheint auch zu funktionieren (der obige Code ist in der Trigger-Procedure/Trigger-Function)
 
Zurück
Oben