gelöst DBTab Update from Table oder in Loop mit "Update Set" Oder ?


Alles rund um die Sprache ABAP®: Funktionsbausteine, Listen, ALV

Moderatoren: Jan, Steff

gelöst DBTab Update from Table oder in Loop mit "Update Set" Oder ?

Beitragvon RIG » 09.03.2018, 11:27

Hallo liebes Forum,

trotz einiger Suche habe ich leider noch keine befriedigende Antwort für eine Fragestellung gefunden.

Folgendes Szenario:

DBTAB_A hat 150 Felder und 1 KeyFeld

Ich möchte nun 2 Werte, nennen wir Sie Feld120 und Feld121, pro Eintrag in der DB updaten, leider keine Konstanten Werte sonst würde "Update Set" gut funktionieren.

Gibt es eine bessere Lösung als Update dbtab_a from table itab?

mit besser meine ich:

von der DBTAB_A benötige ich im Programmverlauf nur eine Handvoll Felder, weshalb ich nur ungern die ganze Tabelle selektieren möchte.
Auch beim Update braucht die DB ja nicht jedes Feld vergleichen und ggf. Updaten sondern nur meine 2 Felder (Feld120 & Feld121) mit dem Schlüssel prüfen.

Ein Update from Table mit einer kurzen Tabelle aus Key + Updatefeldern ist mir nicht bekannt - deshalb nun meine Frage:

- besser Update from Table
- oder besser Update Set in einem Loop?
- oder eine Möglichkeit die ich noch übersehe und besser als die beiden genannten ist.

Ich bin gespannt auf eure Antworten.
RIG
ForumUser
 
Beiträge: 86
Registriert: 27.08.2012, 17:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Sponsor

Alte ABAP-Entwicklerweisheit: Weißt du weder aus noch ein, baust du einen BADI ein

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon lausek » 09.03.2018, 13:14

Mit "keine konstanten Werte" meinst du dass sich die Spalten ändern können, oder?

Ein bisschen Code würde vielleicht helfen, die Problematik etwas klarer zu machen. Btw, welche Release Version hast du?
lausek
ForumUser
 
Beiträge: 60
Registriert: 23.03.2017, 07:54
Dank erhalten: 19 mal
Ich bin: Student/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon DeathAndPain » 09.03.2018, 13:34

Ich verstehe ihn so, dass er bei allen Zeilen zwei Spalten updaten möchte, basierend auf Werten aus anderen Spalten derselben Zeile. Es sind aber dennoch nur wenige Spalten, die er da braucht.

von der DBTAB_A benötige ich im Programmverlauf nur eine Handvoll Felder, weshalb ich nur ungern die ganze Tabelle selektieren möchte.

Was meinst Du mit "Handvoll Felder"? Meinst Du a) "Handvoll Spalten" oder meinst Du b), dass Du nur wenige Zeilen bearbeiten willst?

Wenn a): Mach keinen SELECT *, sondern führe die Spalten, die Du brauchst, explizit auf. Das ist sowieso ordentlicher Programmierstil.

Wenn b): Selektiere halt die Zeilen, die Du brauchst, in eine interne Tabelle. Wenn Du nicht über den Primärschlüssel selektieren solltest, kannst Du ggf. darüber nachdenken, einen zusätzlichen Datenbankindex auf der Datenbanktabelle anzulegen, der zu Deinem Zugriff passt. (Muss natürlich von der Nutzungshäufigkeit her gerechtfertigt sein.)

Letztlich läuft es auf einen LOOP hinaus, bei dem Du die interne Tabelle mit den selektierten Spalten durchhechelst und die zu verändernden Spalten berechnest. Ob Du dann einen UPDATE FROM TABLE oder einen UPDATE SET nimmst, müsste man antesten. UPDATE FROM TABLE wird vermutlich schneller sein, aber in seiner herkömmlichen Form erfordert er, dass Du vorher doch per SELECT * die ganzen anderen Spalten einliest.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon RIG » 09.03.2018, 15:22

lausek hat geschrieben:Mit "keine konstanten Werte" meinst du dass sich die Spalten ändern können, oder?

Ein bisschen Code würde vielleicht helfen, die Problematik etwas klarer zu machen.



Hallo und Danke für die Antworten.
DeathAndPain hat es richtig interpretiert, meine Anforderung als Coding wären:

Code: Alles auswählen
DATA: gt_ztable_150 type STANDARD TABLE OF ztable150. "Tabelle mit ca 150 Spalten

*Variante 1

Select * from ztable into TABLE gt_ztable_150 where field in so_fieldoption.  "gehen wir mal von 1000 Zeilen aus
 
Perform ein_großes_wunder.    "hier werden jetzt die u.a. die Felder 120 & 121 (Feld / Spalte)
                              "mit verschiedensten Werten gefüllt (kaum Zeilen gleich)
Perform db_locks.
 
UPDATE ztable150 from gt_ztable_150.

**************************************************************************************************************  
 
*Variante 2
Select Feld_1 Feld_10 Feld_11 Feld_12 Feld_13 Feld_14 Feld_15 Feld_120 Feld_121
  from ztable150 into TABLE gt_ztable_150_short.  "gt_ztable_150_short könnte ein angepasster Datentyp sein
 
Perform ein_großes_wunder.    "hier werden jetzt die u.a. die Felder 120 & 121 (Feld / Spalte)
                              "mit verschiedensten Werten gefüllt (kaum Zeilen gleich)
Perform db_locks.
 
LOOP AT gt_ztable_150_short ASSIGNING <fs>.
  UPDATE ztable150 set Feld_120 = <fs>-feld_120
                       Feld_121 = <fs>-feld_121
                       where Feld_1 eq <fs>-feld_1.
ENDLOOP.
 


DeathAndPain hat geschrieben:Wenn a): Mach keinen SELECT *, sondern führe die Spalten, die Du brauchst, explizit auf. Das ist sowieso ordentlicher Programmierstil.

Wenn b): Selektiere halt die Zeilen, die Du brauchst, in eine interne Tabelle. Wenn Du nicht über den Primärschlüssel selektieren solltest, kannst Du ggf. darüber nachdenken, einen zusätzlichen Datenbankindex auf der Datenbanktabelle anzulegen, der zu Deinem Zugriff passt. (Muss natürlich von der Nutzungshäufigkeit her gerechtfertigt sein.)

Letztlich läuft es auf einen LOOP hinaus, bei dem Du die interne Tabelle mit den selektierten Spalten durchhechelst und die zu verändernden Spalten berechnest. Ob Du dann einen UPDATE FROM TABLE oder einen UPDATE SET nimmst, müsste man antesten. UPDATE FROM TABLE wird vermutlich schneller sein, aber in seiner herkömmlichen Form erfordert er, dass Du vorher doch per SELECT * die ganzen anderen Spalten einliest.


Eine Mischung aus a & b, in jedem Programmlauf werden zwischen 1000 und 30000 Zeilen selektiert, ich benötige für mein "großes Wunder" nicht all zu viele Spalten der Gesamtbreite, aber für ein Update from Table würde ich eben leider alle spalten benötigen. Der Zugriff auf die Einträge per Key/Index ist Gewährleistet.

Deswegen war meine Frage was besser ist oder ob es eventuell noch einen Charmanteren Weg gibt in dem ich nicht alles Selektieren muss und Trotzdem alles in einem Statement (einer DB-Anfrage) Updaten kann.

Ich habe mich zwischenzeitlich gefragt ob ich den Wald vor Bäumen nicht sehe, da ich aber diese Konstellation so noch nie hatte kam mir jetzt erst diese Fragestellung.
Normalerweise setzt man ja vlt nur Kennzeichen mit Set 'X' where [Bedingung die größere Treffermenge ergibt] - hier ist die Konstellation eben komplizierter und mir ging es darum ob man ein Weg bevorzugen sollte und wenn ja welchen.

lausek hat geschrieben:Btw, welche Release Version hast du?


SAP ECC 6.0

SAP_BASIS 700
SAP_ABA 700
SAP_AP 700
SAP_APPL 600
EA-APPL 600

Vielen Dank nochmal für euere Antworten.
RIG
ForumUser
 
Beiträge: 86
Registriert: 27.08.2012, 17:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon DeathAndPain » 12.03.2018, 11:33

Bei dem alten Release wirst Du um die Wahl zwischen Pest (alles einlesen) und Cholera (zeilenweisen UPDATE SET) nicht herumkommen. Bei 7.50 hättest Du möglicherweise eine Chance gehabt, weil man da in der WHERE-Bedingung auch vergleichsweise komischen Kram angeben darf (möglicherweise wären da auch die von Dir benötigten Vergleiche innerhalb der Tabellenzeile zulässig). Alenfalls könntest Du prüfen, ob Du mit Native SQL was reißen kannst, indem Du mit einem entsprechenden Call das volle Feature Set Deiner Datenbank nutzt.

Auf der anderen Seite: Ich habe zwar auch emotionale Hemmungen, 30.000 Zeilen langer Tabellen zu puffern, aber man muss im Hinterkopf behalten, wie sich die Hauptspeichermengen in den letzten 15 Jahren weiterentwickelt haben. 2003 hatte ein PC vielleicht 512 MB RAM. Server hatten natürlich mehr, aber verglichen mit heutigen Verhältnissen war das auch lächerlich.

Wenn wir jetzt davon ausgehen, dass Deine Tabelle 20 Spalten vom Type CHAR100 hat, dann wäre das ja schon ziemlich opulent. Wenn wir dann noch annehmen, dass jedes Zeichen per Unicode mit 2 Byte codiert wird (was auch schon viel wäre), dann wären das pro Tabellenzeile 20 x 200 x 2 = 8000 Byte oder 8 kB. Davon 30.000 Zeilen macht 30.000 x 8 kB = 240.000 kB = 240 MB. Heutige Server haben Hauptspeicher in der Größenordnung vieler Gigabyte, teilweise liegen sie sogar im Terabytebereich (insbesondere die HANA-Teile). Für zwei Sekunden mal 240 MB zu belegen, um Ausführungszeit zu sparen, finde ich jetzt nicht verwerflich. Wichtig wäre dabei aber, nicht ein Ergebnis-ALV zu bringen, während Deine Hilfstabelle noch im Speicher steht, und der Anwender lässt das ALV dann auf dem Bildschirm stehen und macht erst mal eine halbe Stunde was anderes.

Entweder Deine Hilfstabelle ist eine lokale Tabelle innerhalb eines Unterprogramms, das den UPDATE organisiert - dann wird sie mit Verlassen des Unterprogramms wieder freigegeben (wenn Du nicht so dämlich bist, sie per STATICS zu deklarieren). Oder Du setzt nach Deinem UPDATE einen expliziten FREE-Befehl ab. Dann sollte das im grünen Bereich sein.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon RIG » 12.03.2018, 13:12

Danke an alle für Eure Antworten,
ich tendiere auch zur Lösung des Select * und dann am ende Update from Table - zumal der Report im Hintergrund ausgeführt wird.

Im Dialogmodus hätte ich eventuell 2 Varianten programmiert und dann je nach Selektierter Datenmenge das Update Set im Loop oder eben Update from Table gewählt.
Aber so, habe ich jetzt keine Bauchschmerzen das nur als Update from Table zu implementieren.
RIG
ForumUser
 
Beiträge: 86
Registriert: 27.08.2012, 17:05
Dank erhalten: 0 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon DeathAndPain » 13.03.2018, 13:16

Im Dialogmodus hätte ich eventuell 2 Varianten programmiert und dann je nach Selektierter Datenmenge das Update Set im Loop oder eben Update from Table gewählt.

Wann hättest Du da was wählen wollen? Viele Daten = mehr Hauptspeicher, aber auch mehr laufzeitfressende UPDATE SET-Befehle. Wenn Du Deine Puffertabelle wieder freigibst, bevor Du den ALV anzeigst, dann gibt es technisch keinen relevanten Unterschied zwischen der Ausführung im Hintergrund und der im Dialogbetrieb.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon Daniel » 13.03.2018, 14:27

Du könntest einen VIEW anlegen.
Den darfst du dann mit SELECT * einlesen
und mit UPDATE FROM TABLE fortschreiben.

Für diese Nachricht hat Daniel 3 Dankeschön bekommen :
black_adept, DeathAndPain, RIG
Daniel
Specialist
 
Beiträge: 291
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 33 mal

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon DeathAndPain » 13.03.2018, 14:34

Und der lässt dann alle Spalten, die nicht in den View aufgenommen sind, unangetastet? Das wäre natürlich Klasse. Ich hätte vermutet, dass die dann auf initial gesetzt werden.
DeathAndPain
Expert
 
Beiträge: 814
Registriert: 05.05.2006, 10:14
Dank erhalten: 189 mal
Ich bin: Entwickler/in

Re: DBTab Update from Table oder in Loop mit "Update Set" Od

Beitragvon Daniel » 13.03.2018, 14:37

Was nicht im VIEW definiert ist wird nicht angefasst.
Daniel
Specialist
 
Beiträge: 291
Registriert: 10.09.2003, 13:20
Wohnort: Bielefeld
Dank erhalten: 33 mal


Zurück zu ABAP® Core

  Aktuelle Beiträge   
500 Internal Server Error
vor 4 Stunden von zzcpak 1 Antw.
Dokumentinformationen lesen vom DVS
vor 6 Stunden von Tron 4 Antw.
Tabs innerhalb von Tabs
vor 7 Stunden von ewx 4 Antw.
Fakturierungsplan in Kontrakten ändern
vor 3 Stunden von DeathAndPain 1 Antw.
Scope items
vor 4 Tagen von SAP_ENTWICKLER 0 Antw.

  Ähnliche Beiträge beta
Sperre von Zeilen mit "select for update"
22.11.2006, 11:46 von abapi 7 Antw.
"select for update" vs. händischer Sperre
09.01.2008, 17:50 von edwin 3 Antw.
[ALV] "Layout" cw-width = 'X' vs. "gs_sort" expa ='X'
26.08.2011, 10:46 von black_adept 4 Antw.
gelöst ALV Grid: Problem mit "Cellstyle" und "F4-Hilfe"
15.08.2018, 09:24 von Steffen 16 Antw.
Problem mit "HIDE" und "AT SELECTION-SCREEN&q
26.10.2005, 10:03 von ereglam 1 Antw.

 

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder