Problem Rule bei INSERT und UniqueKey-Feld

Hallo, ich habe eine Regel angelegt, welche das Einfügen von Duplikaten (UniqueKey) bei der Datenübernahme verhindern soll - aber es funktioniert nicht. Auf welchem Auge bin ich blind?

CREATE TABLE bia.taa03
(
  pk_aa03 integer NOT NULL DEFAULT 0,
  pk_aa03_temp SERIAL,
  vorname character varying(50) NOT NULL DEFAULT ''::character varying,
  gilt_bis date NOT NULL DEFAULT '9999-12-31'::date,
  CONSTRAINT pk_aa03 PRIMARY KEY (pk_aa03_temp),
  CONSTRAINT uk_aa03 UNIQUE (vorname)
)
WITH (OIDS=FALSE);
ALTER TABLE bia.taa03 OWNER TO umw_master;
COMMENT ON TABLE bia.taa03 IS 'Katalog Vornamen';
COMMENT ON COLUMN bia.taa03.pk_aa03 IS 'PrimaryKey';
COMMENT ON COLUMN bia.taa03.vorname IS 'Vorname';
COMMENT ON COLUMN bia.taa03.gilt_bis IS 'Gültigkeit des Eintrages';
--
CREATE OR REPLACE RULE insert_ignore AS
    ON INSERT TO bia.taa03
   WHERE (EXISTS ( SELECT true AS bool
           FROM bia.taa03
           WHERE taa03.vorname = new.vorname)) DO INSTEAD NOTHING;
-- Übernahme der Daten
INSERT INTO bia.taa03(vorname) SELECT TRIM(vorname) FROM intranet.taa03;
INSERT INTO bia.taa03(vorname) SELECT TRIM(vorname) FROM aa_daten.taa03;

Ich habe es auch schon mit COUNT() und dann WHERE 0<(SELECT COUNT()… probiert, führt zur gleichen Fehlermeldung.

Wird nun die Übernahme mit INSERT INTO… ausgeführt, erscheint die ungewollte :wink: Fehlermeldung - genau die wollte ich verhindern.

FEHLER:  doppelter Schlüsselwert verletzt Unique-Constraint »uk_aa03«


********** Fehler **********

FEHLER: doppelter Schlüsselwert verletzt Unique-Constraint »uk_aa03«
SQL Status:23505

Hat jemand eine Idee?

Gruß und Dank
Rainer



test=*# select * from ziel;
 name
------
 ich
 du
 er
(3 rows)

test=*# select * from quelle;
 name
------
 ich
 ich
 wir
 wir
 wir
 wir
(6 rows)

test=*# insert into ziel select distinct name from quelle except select name from ziel;
INSERT 0 1
test=*# select * from ziel;
 name
------
 ich
 du
 er
 wir
(4 rows)

Andreas

Hallo Andreas,
Danke für Deine schnelle Hilfe.

Hast Du vielleicht trotzdem noch eine Idee, warum die Regel nicht greift? Für die Datenübernahme ist das so ok, aber für die Anwendung wäre mir die Regel lieber, wenn sie denn wie erwartet funktioniert.

Gruß und Dank
Rainer

Nicht wirklich, hab das mal nachvollzogen:

test=*# create or replace rule insert_ignore as on insert to ziel where (exists (select true from ziel where ziel.name = new.name)) do instead nothing;
CREATE RULE
test=*# insert into ziel select * from quelle;                                                                     
INSERT 0 0

Du hast keinen Fehler beim guttenbergen gemacht?


Andreas

Hallo Andreas,

ich habe Deine Zeile kopiert und angepasst, das “AS bool” wird automatisch ergänzt, aber auch diesmal schlug das Einfügen fehl.

Einen Ansatz habe ich nicht wirklich, da der Aufbau soweit korrekt sein sollte und es bei Dir auch funktioniert. Vielleicht liegt es an den zu übernehmenden Daten, denn wenn ich einen Eintrag per “manueller” Einzelanweisung einfügen möchte, kommt keine Fehlermeldung, die Regel greift also.

Kann es daran liegen, dass hier mehr als ein Datensatz eingefügt wird und die Regel dann nicht greift? Sieht für mich so aus.

Danke nochmals für Deine schnelle Hilfe!

Gruß und Dank Rainer

P.S. Gibt es hier eine Funktion, um einen Thread als “erledigt” zu markieren?

Ich hab eine Vermutung…

Du verwendest eine Funktion, TRIM(), in new solltest Du dann auf diesen neuen Spaltennamen prüfen …


Andreas

Hallo Andreas,

beim Lesen Deines Hinweises kam der Aha-Effekt, ist ja auch völlig verständlich, ungetrimmt <> getrimmt. Aber es geht auch damit nicht. :frowning:

CREATE TABLE bia.taa03
(
  pk_aa03 integer NOT NULL DEFAULT 0,
  pk_aa03_temp SERIAL,
  vorname character varying(50) NOT NULL DEFAULT ''::character varying,
  gilt_bis date NOT NULL DEFAULT '9999-12-31'::date,
  CONSTRAINT pk_aa03 PRIMARY KEY (pk_aa03_temp),
  CONSTRAINT uk_aa03 UNIQUE (vorname)
)
WITH (OIDS=FALSE);
ALTER TABLE bia.taa03 OWNER TO master;
COMMENT ON TABLE bia.taa03 IS 'Katalog Vornamen';
COMMENT ON COLUMN bia.taa03.pk_aa03 IS 'PrimaryKey';
COMMENT ON COLUMN bia.taa03.vorname IS 'Vorname';
COMMENT ON COLUMN bia.taa03.gilt_bis IS 'Gültigkeit des Eintrages';
--
CREATE OR REPLACE RULE insert_ignore AS
    ON INSERT TO bia.taa03
   WHERE (EXISTS ( SELECT true AS bool
           FROM bia.taa03
           WHERE TRIM(taa03.vorname) = TRIM(new.vorname))) DO INSTEAD NOTHING;
-- Übernahme der Daten
INSERT INTO bia.taa03(vorname) SELECT TRIM(vorname) FROM intranet.taa03;
INSERT INTO bia.taa03(vorname) SELECT TRIM(vorname) FROM aa_daten.taa03;

Dann geht meine Vermutung, da ich mich nicht in den “Tiefen” der Arbeitsweise auskenne, dahin, dass es vielleicht daran liegt, dass beim INSERT nicht jeder Datensatz einzeln geschrieben wird, sondern “im Stück”. Nur so lässt es sich erklären, dass, wenn ich die beiden INSERT’s erneut aufrufe, KEINE Fehlermeldung kommt.

Vielen Dank für Deine Hinweise
Gruß Rainer

Nach einem

SELECT TRIM(vorname) FROM intranet.taa03;

enthält Dein NEW kein Feld NEW.name, sondern ein NEW.btrim:

psql (9.2devel)
Type "help" for help.

test=# select trim('  bla ');
 btrim
-------
 bla
(1 row)

Setz mal beim SELECT ein ‘as name’ dahinter:

test=*# select trim('  bla ') as name;
 name
------
 bla
(1 row)

Andreas

Hallo Andreas,

ein “AS irgendwas” schlägt auch fehl :frowning: . Wie geschrieben, wenn ich die beiden INSERT aufrufe nachdem ich den Import mit EXCEPT SELECT erfolgreich durchgeführt habe, “greift” die Regel und es wird keine Fehlermeldung generiert.

Gruß und Dank
Rainer