Trigger zum duplizieren von Zeilen

PaulMueller

Benutzer
Beiträge
12
Hallo,

ich möchte nach Eingabe eines Datensatzes einen Trigger laufen lassen, der prüft ob ein bestimmter Wert in einer Spalte (Blockorderanzahl) höher als 1 ist, dann soll die entsprechende Zeile nochmal in die Tabelle hinzugefügt werden und zwar so oft wie der Wert in der Spalte.
Ich habe das mit dem Trigger siehe unten konfiguriert, aber er macht nicht das was er soll.
Wenn der entsprechende Wert 1 ist, dann passiert nicht, somit in Ordnung
Wenn der Wert 2 ist passiert auch nichts, und in diesem Fall müssten die Daten in einer neuen Zeile wieder stehen.
bei dem Wert 3 passiert im Prinzip auch nichts, außer dass der Primary Key zwei Werte auslässt. Es findet keine Duplizierung statt.
Ab einem Wert von 4 bekomme ich den Fehler:
Error Code: 1054. Unknown column 'blockorderanzahl' in 'field list'
Der normale Insert befehl, der funktioniert, wenn der Trigger gelöscht wird. Der Primary Key ist die Kauforder_ID, Fremdschlüssel sind kunde_id und produkt_id

INSERT INTO kauforder (order_ID, initial_ID, parent_ID, startzeitpunkt, endzeitpunkt, stornierzeitpunkt, kunde_id, produkt_id, lieferzeitpunkt, preis, menge, blockorder, blockorderanzahl)
VALUES (null,null,null,CURRENT_TIMESTAMP,'2020-01-02 15:00:00',null,(SELECT marktteilnehmer_ID from marktteilnehmer WHERE marktteilnehmername = 'TenneT'),(SELECT produkt_id from produkt WHERE produktname = 'Stunde'),'16:00','15','150','ja','4');
UPDATE kauforder SET order_id = kauforder_id, initial_id= kauforder_id WHERE kauforder_id = LAST_INSERT_id();


Hier der Trigger:

CREATE DEFINER=`root1`@`%` TRIGGER `orderbuch`.`kauforder_AFTER_INSERT` AFTER INSERT ON `kauforder` FOR EACH ROW
BEGIN
DECLARE anzahl integer;
SET anzahl=(SELECT blockorderanzahl FROM kauforder WHERE kauforder_id = LAST_INSERT_id());
IF anzahl>1 THEN
WHILE anzahl <= blockorderanzahl do
INSERT INTO kauforder
(order_ID, initial_ID, parent_ID, startzeitpunkt, endzeitpunkt, stornierzeitpunkt, kunde_id, produkt_id, lieferzeitpunkt, preis, menge, blockorder)
VALUES ((SELECT kauforder_id WHERE kauforder_id = LAST_INSERT_id()),(SELECT kauforder_id WHERE kauforder_id = LAST_INSERT_id()),null,(SELECT startzeitpunkt WHERE kauforder_id = LAST_INSERT_id()),'2020-01-02 15:00:00',null,(SELECT kunde_id from kunde WHERE kunde = 'Mueller'),(SELECT produkt_id from produkt WHERE produktname = 'Stunde'),'16:00','15','150','ja');

END while;
END IF;
END


Ich hoffe ihr könnt mir weiterhelfen.

Danke und Grüße
 
Werbung:
Ich halte die Idee für nicht ganz zuende gedacht. Was passiert, wenn Du z.B. dann 5 mal denselben Datensatz hast, und bei einem dann das Anzahl-Feld auf 3, bei einem anderen auf 12 und bei noch einem anderen auf 42 änderst? Was soll passieren, wenn von den 5 später 3 gelöscht werden? Das ist alles nicht konsistent.

Was spricht dagegen, beim Abruf on-the-fly die Datensätze zu erzeugen?

Code:
test=*# create table paulmueller (id int generated always as identity, wert text, anzahl int);
CREATE TABLE
test=*# insert into paulmueller (wert, anzahl) values ('demo',3);
INSERT 0 1
test=*# insert into paulmueller (wert, anzahl) values ('test',2);
INSERT 0 1
test=*# insert into paulmueller (wert, anzahl) values ('bla',5);
INSERT 0 1
test=*# select * from paulmueller;
 id | wert | anzahl
----+------+--------
  1 | demo |      3
  2 | test |      2
  3 | bla  |      5
(3 rows)
test=*# select p.* from paulmueller p left outer join lateral (select * from generate_series(1,p.anzahl)) x on true;
 id | wert | anzahl
----+------+--------
  1 | demo |      3
  1 | demo |      3
  1 | demo |      3
  2 | test |      2
  2 | test |      2
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
(10 rows)

Das kann ja auch eine VIEW dann sein...
 
Das entsprechende Feld wird nie wieder geändert. Der Datensatz kann höchstens storniert werden bzw. andere Felder werden geändert und dann wird der Ursprüngliche Datensatz mit einem Endzeitpunkt versehen.

On the fly ist blöd, da ich ein Drop down Menü erstellt habe von 1 bis 24, so dass man als Benutzer sagen kann ich will x-mal ein Produkt zu gleichem Preis, aber unterschiedlichen Lieferzeitpunkt haben. Die Eintragung soll dann x mal automatisch passieren. Der Lieferzeitpunkt müsste dann immer um x auch erhöht werden.

Ich hatte gehofft, man kann das als Schleife realisieren.
 
Davon abgesehen:

  • ein TRIGGER, der bei einem Insert wieder ein Insert in diese Tabelle macht, dürfte sich (wenn er funktioniert) immer wieder solange aufrufen, bis es explodiert
  • deine last_insert_id() - Aufrufe liefern was? Die vom originalen Insert, oder die von Trigger generierten Inserts? Was erwartest Du?
  • Deine Laufvariable scheint nicht runtegezählt zu werden
  • in der Schleifen stehen jede Menge fester Werte (Urzeit, Kunde = 'Mueller' etc.) Das sieht absolut krank aus, sorry

tl;dr

ich denke nicht, daß das funktionieren wird. Aber dennoch viel Spaß damit!
 
oh ja, das könnte wirklich "explodieren".


gibt es irgendwie sonst die Möglichkeit einen Datensatz mehrmals automatisch (so oft wie bestimmter Spaltenwert) in eine Tabelle eintragen lassen?
Der Benutzer der GUI soll am Ende nur einen Datensatz eintragen und anhand eines Wertes soll die DB wissen, dass der Datensatz mehrmals eingetragen werden soll.

Ich bin irgendwie überfragt :/
 
Meine Abfrage, und damit ein erstellter VIEW, löst alle Deine Probleme.

Nun ja, fast. MySQL kann weder LATERAL JOIN noch generate_series().

Code:
test=*# create view view_paulmueller as select p.* from paulmueller p left outer join lateral (select * from generate_series(1,p.anzahl)) x on true;
CREATE VIEW
test=*#
test=*#
test=*# select * from view_paulmueller ;
 id | wert | anzahl
----+------+--------
  1 | demo |      3
  1 | demo |      3
  1 | demo |      3
  2 | test |      2
  2 | test |      2
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
  3 | bla  |      5
(10 rows)
 
Werbung:
Na gut, weil Du es bist:

Code:
test=# create table paulmueller2 (id int generated always as identity, wert text, anzahl int, flag bool default false);
CREATE TABLE
test=*# create or replace function insert_records() returns trigger as $$begin insert into paulmueller2 (wert, anzahl, flag) select new.wert, new.anzahl, true from generate_series (1, new.anzahl-1) x ; return new;end;$$language plpgsql;
CREATE FUNCTION
test=*# create trigger trg1 after insert on paulmueller2 for each row when (new.flag is false) execute function insert_records();
CREATE TRIGGER
test=*# insert into paulmueller2 (wert, anzahl) values ('test',3);
INSERT 0 1
test=*# select * from paulmueller2;
 id | wert | anzahl | flag
----+------+--------+------
  1 | test |      3 | f
  2 | test |      3 | t
  3 | test |      3 | t
(3 rows)

Achtung, das ist ein conditional trigger, er hat in der Definition des Triggers eine Where-Condition. Ich nutze ein extra Feld, hier 'flag' genannt und per default false. Die neu eingefügten Records durch den Trigger haben dort dann ein true, damit es nicht explodiert.

Ach ja, conditional trigger kann MySQL selbstverständlich auch nicht. Wäre echt zu cool.
 
Zurück
Oben