Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Datensaetze duplizieren

8 views
Skip to first unread message

Stefan Froehlich

unread,
Mar 12, 2013, 2:15:52 PM3/12/13
to
Ich versuche mich gerade darin, Kopien von (komplexeren, im Sinn von:
mehrere ueber foreign keys verbundene Tabellen umfassende) Datensaetzen
direkt in der Datenbank zu erstellen (das alles in PostgreSQL).

Der erste Schritt dazu ist die Erstellung des Records _einer_ Tabelle:

| # INSERT INTO foo (SELECT * FROM foo WHERE id=1);
| ERROR: duplicate key value violates unique constraint "foo_pkey"

Ok, so weit, so klar. Was ich nun aber definitiv NICHT will, ist alle
Felder einzeln aufzuzaehlen - das wuerde unuebersichtlich gross und auch
deutlich schlechter wartbar.

Also definiere ich den primary key als "deferrable" und mache:

| # BEGIN;
| # INSERT INTO foo (SELECT * FROM foo WHERE id=1);

Klappt ja wunderbar. Der zweite Schritt waere nun, dem neuen Record eine
eigene Id zuzuweisen:

| # UPDATE foo SET id=nextval('foo_id_seq'::regclass) WHERE ?!?;

Tja. Aber was schreibe ich nun in die WHERE-Bedingung? Es existieren ja
zwei identische Records, aber nur einer davon soll aktualisiert werden...

Hat jemand Ideen dazu?

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - das antiquiertste Ansinnen des Jahrtausends.
(Sloganizer)

Wolfgang May

unread,
Mar 12, 2013, 2:54:11 PM3/12/13
to
Stefan Froehlich <Stefan...@froehlich.priv.at> wrote:
> Ich versuche mich gerade darin, Kopien von (komplexeren, im Sinn von:
> mehrere ueber foreign keys verbundene Tabellen umfassende) Datensaetzen
> direkt in der Datenbank zu erstellen (das alles in PostgreSQL).
>
> Der erste Schritt dazu ist die Erstellung des Records _einer_ Tabelle:
>
> | # INSERT INTO foo (SELECT * FROM foo WHERE id=1);
> | ERROR: duplicate key value violates unique constraint "foo_pkey"
>
> Ok, so weit, so klar. Was ich nun aber definitiv NICHT will, ist alle
> Felder einzeln aufzuzaehlen - das wuerde unuebersichtlich gross und auch
> deutlich schlechter wartbar.
>
> Also definiere ich den primary key als "deferrable"
>
> und mache:
>
> | # BEGIN;
> | # INSERT INTO foo (SELECT * FROM foo WHERE id=1);
>
> Klappt ja wunderbar. Der zweite Schritt waere nun, dem neuen Record eine
> eigene Id zuzuweisen:
>
> | # UPDATE foo SET id=nextval('foo_id_seq'::regclass) WHERE ?!?;
>
> Tja. Aber was schreibe ich nun in die WHERE-Bedingung? Es existieren ja
> zwei identische Records, aber nur einer davon soll aktualisiert werden...
>
> Hat jemand Ideen dazu?

Unterstuetzt PostgreSQL die Pseudo-Spalte rowid?
mach mal
select id,rowid from foo;
Jede Zeile muesste eine eigene rowid haben.

Dann kannste

UPDATE foo a
SET id=nextval('foo_id_seq'::regclass)
WHERE id = max (select b.rowid from foo b where b.id=a.id)

machen.

Wolfgang

Lutz Donnerhacke

unread,
Mar 12, 2013, 6:36:55 PM3/12/13
to
* Wolfgang May wrote:
> Unterstuetzt PostgreSQL die Pseudo-Spalte rowid?

Nein, oid. Das bekommt man beim INSERT zur�ck.
Und kann dann "UPDATE ... WHERE oid = ?" gezielt einsetzen.

Tim Landscheidt

unread,
Mar 12, 2013, 6:51:34 PM3/12/13
to
... wenn die Tabelle OIDs hat
(vgl. http://www.postgresql.org/docs/8.1/static/datatype-oid.html):

| Object identifiers (OIDs) are used internally by PostgreSQL
| as primary keys for various system tables. OIDs are not
| added to user-created tables, unless WITH OIDS is specified
| when the table is created, or the default_with_oids configu-
| ration variable is enabled. [...]

(Kam 8.1 wirklich schon 2005 heraus? Mamma mia.)

Tim

Stefan Froehlich

unread,
Mar 13, 2013, 4:05:34 AM3/13/13
to
On Tue, 12 Mar 2013 23:36:55 Lutz Donnerhacke wrote:
> * Wolfgang May wrote:
> > Unterstuetzt PostgreSQL die Pseudo-Spalte rowid?

> Nein, oid. Das bekommt man beim INSERT zurück.
> Und kann dann "UPDATE ... WHERE oid = ?" gezielt einsetzen.

Merci, das trifft genau den Punkt.

(Oids einschalten geht zum Glueck auch nachtraeglich noch ganz ohne
Schmerzen. Wesentlich unangenehmer ist die Aenderung des Primary Keys
auf "deferrable", aber da muss ich halt durch).

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan - die schlimmste Versuchung seit Konrad Zuse.
(Sloganizer)

Florian Weimer

unread,
Mar 13, 2013, 4:16:18 AM3/13/13
to
* Stefan Froehlich:

> Ich versuche mich gerade darin, Kopien von (komplexeren, im Sinn von:
> mehrere ueber foreign keys verbundene Tabellen umfassende) Datensaetzen
> direkt in der Datenbank zu erstellen (das alles in PostgreSQL).

DO $$
DECLARE
f foo%ROWTYPE;
BEGIN
SELECT INTO f * FROM foo WHERE id = 1;
f.id := nextval('foo_id_seq'::regclass);
INSERT INTO foo VALUEs (f.*);
END;
$$ LANGUAGE plpgsql;

Mit einer tempor�ren Tabelle ginge das auch, ist aber wegen der
Katalog�nderung vermutlich deutlich langsamer.

Andreas Scherbaum

unread,
Mar 13, 2013, 5:21:55 AM3/13/13
to
Lutz Donnerhacke <lu...@iks-jena.de> wrote:
> * Wolfgang May wrote:
>> Unterstuetzt PostgreSQL die Pseudo-Spalte rowid?
>
> Nein, oid. Das bekommt man beim INSERT zurᅵck.
> Und kann dann "UPDATE ... WHERE oid = ?" gezielt einsetzen.

Du willst doch nicht wirklich Tabellen mit oid haben ;-)

--
Andreas 'ads' Scherbaum
Failure is not an option. It comes bundled with your Microsoft product.
(Ferenc Mantfeld)

Lutz Donnerhacke

unread,
Mar 13, 2013, 6:36:21 AM3/13/13
to
* Andreas Scherbaum wrote:
> Du willst doch nicht wirklich Tabellen mit oid haben ;-)

Ich schon. 32bit sind mir genug.

Stefan Froehlich

unread,
Mar 14, 2013, 5:30:33 AM3/14/13
to
On Wed, 13 Mar 2013 09:16:18 Florian Weimer wrote:
> DO $$
> DECLARE
> f foo%ROWTYPE;
> BEGIN
> SELECT INTO f * FROM foo WHERE id = 1;
> f.id := nextval('foo_id_seq'::regclass);
> INSERT INTO foo VALUEs (f.*);
> END;
> $$ LANGUAGE plpgsql;

Huebsch. Sieht auf den ersten Blick zwar komplizierter aus, gestaltet sich
aber gerade bei komplexeren Tabellen sehr elegant (und kommt vor allem ohne
Oids und deferred primary keys aus).

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Für die Dame von Welt - flörten mit Stefan!
(Sloganizer)
0 new messages