Skip site navigation (1) Skip section navigation (2)

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 (view raw or flat)
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

pgsql-de-allgemein by date

Next:From: Rainer LayDate: 2008-03-11 07:54:49
Subject: Re: Check Constraint mit Subselect
Previous:From: Olaf RadickeDate: 2008-03-10 14:12:39
Subject: Re: Check Constraint mit Subselect

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group