Forum: PC-Programmierung PostgreSQL: PL/pgSQL für dieses INSERT notwendig ?


von Slonovi (Gast)


Lesenswert?

Hallo,

ich würde gerne mit pgAdmin eine .csv Datei in eine psql-Datenbank 
einspielen.

Die .csv Datei enthält die Tabelle bulk_prices mit den Spalten:
1
 
2
partnumber|name|type|price|quantity
3
----------|----|----|-----|--------
4
1000      |sdf |c   |12.43|5
5
1000      |xyz |c   |10.20|10
6
1001      |abc |v   |34.99|8
7
...
Diese Daten sollen in je zwei Tabellen aufgeteilt werden:

Tabelle price_rules:
1
 
2
id|name|type|price
3
--|----|----|-----
4
1 |sdf |c   |12.43
5
2 |xyz |c   |10.20
6
3 |abc |v   |34.99
7
...
Tabelle price_rule_items:
1
 
2
id|price_rules_id|type|op|value_int|value_num
3
--|--------------|----|--|---------|---------
4
1 |1             |part|  |1568     |         
5
2 |1             |qty |ge|         |5
6
3 |2             |part|  |1568     |         
7
4 |2             |qty |ge|         |10
8
5 |3             |part|  |6532     |         
9
6 |3             |qty |ge|         |8
10
...
Folgende "inserts" sollen also getätigt werden:
1
bulk_prices.name  -> price_rules.name
2
bulk_prices.type  -> price_rules.type
3
bulk_prices.price -> price_rules.price
Die eindeutige ID (price_rules.id) die bei jedem Eintrag in der Tabelle 
vergeben wird, soll jetzt mit den dazugehörigen Regeln in der Tabelle 
price_rules_id verknüpft werden.
Für jede "price_rule" sollen jeweils zwei "price_rule_items" angelegt 
werden:

Erster Eintrag:
1
price_rules.id -> price_rule_items.price_rules_id
2
'part'         -> price_rule_items.type
3
parts.id       -> price_rule_items.value_int
Zweiter Eintrag:
1
price_rules.id       -> price_rule_items.price_rules_id
2
'qty'                -> price_rule_items.type
3
'ge'                 -> price_rule_items.op
4
bulk_prices.quantity -> price_rule_items.value_num
Die eindeutige price_rules.id soll aus der Tabelle "parts" übernommen 
werden:
1
 
2
Tabelle "parts":
3
id  |partnumber
4
----|----------
5
1568|1000
6
...
7
6532|1001
8
...
Leider schaffe ich es nicht eine passende SQL "Abfrage" zu erstellen. 
Ich habe meinen fehlerhaften Code mal auf SQLfiddle hochgeladen: 
http://sqlfiddle.com/#!17/e5b6c/3

Für einen Eintrag in staffelpreise_tmp funktioniert der Code. Aber 
sobald man mehr Einträge durch entfernen der "Auskommentierungen" 
hinzufügt, enstehen fehlerhafe Mehrfacheinträge. Vermutlich durch die 
implizierte INNER JOIN (WHERE staffelpreise_tmp.partnumber = 
parts.partnumber;), welche nach bei jedem hinzufügen und aufrufen mehr 
"matches" findet.

Ich habe schon versucht, das mit einem CURSOR und FETCH zu lösen, so 
dass immer nur der gerade "abgearbeitete" staffelpreise_tmp.partnumber 
Wert genommen wird, aber das bekomm ich irgendwie nicht hin.

Kann man diese INSERTS vielleich nur mit z.B. PL/pgSQL (FOR,IF,...) 
lösen ?
Oder bekommt man das noch mit "reinem" SQL hin ?

Ich würde mich sehr freuen, wenn mir jemand mit diesem Problem helfen 
könnte.

LG, Benjamin

von leo (Gast)


Lesenswert?

Slonovi schrieb:
> id|price_rules_id|type|op|value_int|value_num
> --|--------------|----|--|---------|---------
> 1 |1             |part|  |1568     |
> 2 |1             |qty |ge|         |5

Das schaut suboptimal aus. Teile diese Tabelle in "part" und 
"qty"-Tabellen. Das vereinfacht die Sache sicher.

leo

von Slonovi (Gast)


Lesenswert?

Hi,
das ist leider keine leichte Option, da die Datenbank zu einem 
ERP-System gehört, das ich nicht "komplett" umschreiben möchte... "part" 
und "qty" sind auch nur zwei, von mehreren möglichen Einträgen.

von leo (Gast)


Lesenswert?

Slonovi schrieb:
> das ist leider keine leichte Option, da die Datenbank zu einem
> ERP-System gehört,

Vielleicht kannst du trotzdem einige mehr normalisierte Tabellen anlegen 
und dann passende Views fuers ERP drueberlegen. Das Einfuegen usw. ist 
dann halt deutlich einfacher.

leo

von Clemens L. (c_l)


Lesenswert?

INSERT ... RETURNING geht nicht, weil keine der beiden Tabellen genug 
Daten enthält, um den ursprünglichen Record zu identifizieren.

Ein INSTEAD-OF-INSERT-Trigger auf einem View ginge auch, aber da sind 
INSERTs in einer Schleife einfacher.

Was für ein Problem hast du denn mit CURSOR/FETCH?

von c-hater (Gast)


Lesenswert?

Slonovi schrieb:

> ich würde gerne mit pgAdmin eine .csv Datei in eine psql-Datenbank
> einspielen.
>
> Die .csv Datei enthält die Tabelle bulk_prices mit den Spalten:
>
1
> partnumber|name|type|price|quantity
2
> ----------|----|----|-----|--------
3
> 1000      |sdf |c   |12.43|5
4
> 1000      |xyz |c   |10.20|10
5
> 1001      |abc |v   |34.99|8
6
> ...
7
>
> Diese Daten sollen in je zwei Tabellen aufgeteilt werden:
>
> Tabelle price_rules:
>
1
> id|name|type|price
2
> --|----|----|-----
3
> 1 |sdf |c   |12.43
4
> 2 |xyz |c   |10.20
5
> 3 |abc |v   |34.99
6
> ...
7
>
> Tabelle price_rule_items:
>
1
> id|price_rules_id|type|op|value_int|value_num
2
> --|--------------|----|--|---------|---------
3
> 1 |1             |part|  |1568     |
4
> 2 |1             |qty |ge|         |5
5
> 3 |2             |part|  |1568     |
6
> 4 |2             |qty |ge|         |10
7
> 5 |3             |part|  |6532     |
8
> 6 |3             |qty |ge|         |8
9
> ...
10
>

Du zeigst, dass du so wirklich rein garnicht abstrakt denken kannst...


Jede deiner beiden Zieltabellen enthält Daten, die in der Quelltabelle 
schlicht und einfach nicht drinstehen. Dementsprechgend ist es ohne 
weitere Angaben vollkommen unmöglich, sie zu generieren.

Ganz egal mit welchen Mitteln (insbesondere auch: in welcher Sprache).

Das würde nur gehen, wenn du die "..." in der Darstellung der 
Tabelleninhalte weggelassen hättest. Dann wären es alles endliche und 
bestimmte Mengen gewesen und die Lösung wäre vollkommen trivial.

Auch wieder:

Ganz egal mit welchen Mitteln (insbesondere auch: in welcher Sprache).


Fazit: Wenn du willst, dass andere Leute dein Arbeit machen, musst du 
mindestens mit mehr Informationen dafür bezahlen. So sieht's aus.

Du könntest aber statt dessen auch einfach lernen zu denken und SQL als 
Sprachkonzept zu verstehen, um dann am Ende den Job tatsächlich selber 
erledigen zu können. Und dann vielleicht auch den nächsten...

von Clemens L. (c_l)


Lesenswert?

c-hater schrieb:
> Jede deiner beiden Zieltabellen enthält Daten, die in der Quelltabelle
> schlicht und einfach nicht drinstehen. Dementsprechgend ist es ohne
> weitere Angaben vollkommen unmöglich, sie zu generieren.

Und diese weiteren Angaben stehen weiter unten.
1
DO $$
2
  DECLARE
3
    r staffelpreise_tmp%ROWTYPE;
4
    rule_id price_rules.id%TYPE;
5
  BEGIN
6
    FOR r IN SELECT partnumber, name, type, price, quantity FROM staffelpreise_tmp
7
    LOOP
8
      INSERT INTO price_rules(name, type, price)
9
      VALUES (r.name, r.type, r.price)
10
      RETURNING id INTO rule_id;
11
12
      INSERT INTO price_rule_items(price_rules_id, type, value_int)
13
      VALUES (rule_id, 'part', (SELECT id FROM parts WHERE partnumber = r.partnumber));
14
15
      INSERT INTO price_rule_items(price_rules_id, type, op, value_num)
16
      VALUES (rule_id, 'qty', 'ge', r.quantity);
17
    END LOOP;
18
  END
19
$$;

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.