Re: Check Constraint mit Subselect

From: "A(dot) Kretschmer" <andreas(dot)kretschmer(at)schollglas(dot)com>
To: pgsql-de-allgemein(at)postgresql(dot)org
Subject: Re: Check Constraint mit Subselect
Date: 2008-03-11 07:44:55
Message-ID: 20080311074455.GB22544@a-kretschmer.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-de-allgemein

am Mon, dem 10.03.2008, um 12:15:06 +0100 mailte A. Kretschmer folgendes:
> am Mon, dem 10.03.2008, um 11:46:06 +0100 mailte Thomas Guettler folgendes:
> > Hallo,
> >
> > Check Constraints können keine Subselects enthalten.
> >
> > Wie kann ich dann sicherstellen, dass es bei einer 1:N Beziehung, N
> > nicht Null sein darf.
> > Es muss also mindestens einen Datensatz geben.
> >
> > Beispiel: Zu einer Rechnung muss es immer Rechnungspositionen geben.
>
> Du könntest ja eine Function aufrufen, aber Du hast dann ein
> Henne-Ei-Problem: In dem Moment, wo Du die Rechnung erzeugst, steht in
> der Positionstabelle noch kein Record. Man kann aber Constraints
> deferrable setzen und in der TX das nutzen.
>
> Reicht das Dir weiter?

Mal ein Beispiel, wie sowas geht:

--
-- ich erstelle 2 Tabellen, master und slave
--
test=# create table master (id serial primary key, d date);
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 (id serial primary key, m int references master deferrable not null, i int);
NOTICE: CREATE TABLE will create implicit sequence "slave_id_seq" for serial column "slave.id"
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "slave_pkey" for table "slave"
CREATE TABLE
--
-- bis hier simpel, Master-Detail-Tabelle
-- nun noch, daß kein Eintrag in master sein kann, wenn es keinen Eintrag in slave gibt
-- dazu eine weitere Spalte via alter table, die eine Referenz auf slave darstellt
--
test=*# alter table master add column s int references slave deferrable not null;
ALTER TABLE
--
-- nun haben wir ein Henne-Ei-Problem, das zu lösen müssen wir constraints deferred setzen
--
test=*# set constraints all deferred;
SET CONSTRAINTS
--
-- nun können wir, innerhalb einer TX, auch mal Constraints verletzen, was wir ja tun müssen
--
test=*# insert into master (d,s) values (current_date,0);
INSERT 0 1
test=*# insert into slave(m, i) values (currval('master_id_seq'), 10);
INSERT 0 1
test=*# update master set s=currval('slave_id_seq') where id=currval('master_id_seq');
UPDATE 1
test=*# select * from master;
id | d | s
----+------------+---
1 | 2008-03-11 | 1
(1 row)

test=*# select * from slave;
id | m | i
----+---+----
1 | 1 | 10
(1 row)

test=*# commit;
COMMIT
--
-- noch einmal, ohne daß Constraints deferred sind
--
test=# insert into master (d,s) values (current_date,0);
ERROR: insert or update on table "master" violates foreign key constraint "master_s_fkey"
DETAIL: Key (s)=(0) is not present in table "slave".
test=!#
--
-- sehr schön, oder?
--

--
Andreas Kretschmer
Kontakt: Heynitz: 035242/47150, D1: 0160/7141639 (mehr: -> Header)
GnuPG-ID: 0x3FFF606C, privat 0x7F4584DA http://wwwkeys.de.pgp.net

In response to

Responses

Browse pgsql-de-allgemein by date

  From Date Subject
Next Message Rainer Lay 2008-03-11 07:54:49 Re: Check Constraint mit Subselect
Previous Message Olaf Radicke 2008-03-10 14:12:39 Re: Check Constraint mit Subselect