mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Slonovi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
 
partnumber|name|type|price|quantity
----------|----|----|-----|--------
1000      |sdf |c   |12.43|5
1000      |xyz |c   |10.20|10
1001      |abc |v   |34.99|8
...
Diese Daten sollen in je zwei Tabellen aufgeteilt werden:

Tabelle price_rules:
 
id|name|type|price
--|----|----|-----
1 |sdf |c   |12.43
2 |xyz |c   |10.20
3 |abc |v   |34.99
...
Tabelle price_rule_items:
 
id|price_rules_id|type|op|value_int|value_num
--|--------------|----|--|---------|---------
1 |1             |part|  |1568     |         
2 |1             |qty |ge|         |5
3 |2             |part|  |1568     |         
4 |2             |qty |ge|         |10
5 |3             |part|  |6532     |         
6 |3             |qty |ge|         |8
...
Folgende "inserts" sollen also getätigt werden:
bulk_prices.name  -> price_rules.name
bulk_prices.type  -> price_rules.type
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:
price_rules.id -> price_rule_items.price_rules_id
'part'         -> price_rule_items.type
parts.id       -> price_rule_items.value_int
Zweiter Eintrag:
price_rules.id       -> price_rule_items.price_rules_id
'qty'                -> price_rule_items.type
'ge'                 -> price_rule_items.op
bulk_prices.quantity -> price_rule_items.value_num 
Die eindeutige price_rules.id soll aus der Tabelle "parts" übernommen 
werden:
 
Tabelle "parts":
id  |partnumber
----|----------
1568|1000
...
6532|1001
...
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

Autor: leo (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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

Autor: Slonovi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: leo (Gast)
Datum:

Bewertung
1 lesenswert
nicht 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

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
>
> partnumber|name|type|price|quantity
> ----------|----|----|-----|--------
> 1000      |sdf |c   |12.43|5
> 1000      |xyz |c   |10.20|10
> 1001      |abc |v   |34.99|8
> ...
> 
> Diese Daten sollen in je zwei Tabellen aufgeteilt werden:
>
> Tabelle price_rules:
>
> id|name|type|price
> --|----|----|-----
> 1 |sdf |c   |12.43
> 2 |xyz |c   |10.20
> 3 |abc |v   |34.99
> ...
> 
> Tabelle price_rule_items:
>
> id|price_rules_id|type|op|value_int|value_num
> --|--------------|----|--|---------|---------
> 1 |1             |part|  |1568     |
> 2 |1             |qty |ge|         |5
> 3 |2             |part|  |1568     |
> 4 |2             |qty |ge|         |10
> 5 |3             |part|  |6532     |
> 6 |3             |qty |ge|         |8
> ...
> 

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...

Autor: Clemens L. (c_l)
Datum:

Bewertung
0 lesenswert
nicht 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.
DO $$
  DECLARE
    r staffelpreise_tmp%ROWTYPE;
    rule_id price_rules.id%TYPE;
  BEGIN
    FOR r IN SELECT partnumber, name, type, price, quantity FROM staffelpreise_tmp
    LOOP
      INSERT INTO price_rules(name, type, price)
      VALUES (r.name, r.type, r.price)
      RETURNING id INTO rule_id;

      INSERT INTO price_rule_items(price_rules_id, type, value_int)
      VALUES (rule_id, 'part', (SELECT id FROM parts WHERE partnumber = r.partnumber));

      INSERT INTO price_rule_items(price_rules_id, type, op, value_num)
      VALUES (rule_id, 'qty', 'ge', r.quantity);
    END LOOP;
  END
$$;

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.