Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Getting started ... Alles für einen gelungenen Start.
11 Beiträge • Seite 1 von 1
11 Beiträge Seite 1 von 1

Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von Sonne1234 (ForumUser / 30 / 17 / 2 ) »
Hallo zusammen,

ich habe eine interne Tabelle mit Einträgen, die ich in eine Datenbanktabelle übernehmen möchte. Mit einem Modify bekomme ich das auch hin. Hier nur ein kleiner Ausschnitt des Programms bzgl. des Modifys:

Code: Alles auswählen.

types: BEGIN OF ty_toa01,
         mandt      TYPE toa01-mandt,
         sap_object TYPE toa01-sap_object,
         object_id  TYPE toa01-object_id,
         archiv_id  TYPE toa01-archiv_id,
         arc_doc_id TYPE toa01-arc_doc_id,
         ar_object  TYPE toa01-ar_object,
         ar_date    TYPE toa01-ar_date,
         del_date   TYPE toa01-del_date,
         reserve    TYPE toa01-reserve,
       END OF ty_toa01. 

types:  tty_toa01 TYPE SORTED TABLE OF ty_toa01 WITH NON-UNIQUE KEY arc_doc_id. 

FORM f_toa01
  CHANGING p_toa01 TYPE tty_toa01

    MODIFY toa01 FROM TABLE p_toa01.

endform. 
Mir gefällt der Modify aber nicht, da ich eigentlich prüfen möchte, ob es schon einen gleichen Eintrag in der Datenbanktabelle gibt.

Deshalb dachte ich, ich könnte hier einen insert verwenden. Sobald ich jedoch ein modify durch ein insert austausche, kriege ich bei Ausführung des Programms einen Laufzeitfehler. Die Meldung ist auch grundsätzlich richtig, da es in meinem Beispiel einen bereits vorhandenen Eintrag in der TOA01 gibt. Allerdings möchte ich nicht, dass das Programm hier abbricht.
Ich hatte gedacht, dass ich hier evtl. sy-subrc abfragen kann. Aber trotz der folgenden Abfrage führt mein Programm zum Programmierfehler.

Code: Alles auswählen.

 insert toa01 from table p_toa01.

      If sy-subrc = 4.

        write 'Fehler'.
     endif.
Kann mir hier jemand bitte weiterhelfen?

Ich hatte mir hierzu zwar auch schon den folgenden Beitrag angesehen:
viewtopic.php?f=1&t=24036&p=94045&hilit ... lle#p94045

Aber so richtig bin ich damit nicht weiter gekommen.

Oder welchen Befehl muss ich verwenden, wenn ich nur Einträge aus meiner internen Tabelle übernehmen möchte, die noch nicht in der Datenbanktabelle vorhanden sind. (Eigentlich sollten die Einträge noch nicht vorhanden sein, aber ich möchte hier sicher gehen.)

Liebe Grüße
Julia

gesponsert
Stellenangebote auf ABAPforum.com schalten
kostenfrei für Ausbildungsberufe und Werksstudenten


Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von black_adept (Top Expert / 4080 / 125 / 934 ) »
Hallo Julia,

einfach mal die F1-Hilfe zum Befehlt "INSERT" lesen. ( Hinweis. ACCEPTING DUPLICATE KEYS )
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von Sonne1234 (ForumUser / 30 / 17 / 2 ) »
Hallo black_adept,

sorry, ich habe "accepting duplicate keys" immer so verstanden, dass ein doppelter Eintrag erzeugt wird.

Mit ACCEPTING DUPLICATE KEYS scheint es nun zu funktionieren.

Habe ich evtl. auch die Möglichkeit, die Einträge, die in die Datenbanktabelle übernommen worden sind, als Liste auszugeben? Also ich möchte gerne am Ende meines Programms eine Ergebnisliste ausgeben. Eigentlich dachte ich, dass ich einfach meine interne Tabelle TOA01 ausgebe. Allerdings wäre dies nun falsch, da ja ein doppelter Eintrag nicht übernommen wurde.

Vielen Dank.

Gruß
Julia

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von jocoder (Specialist / 343 / 3 / 102 ) »
sorry, ich habe "accepting duplicate keys" immer so verstanden, dass ein doppelter Eintrag erzeugt wird.
In der Hilfe steht:
Wenn der Zusatz ACCEPTING DUPLICATE KEYS angegeben ist, werden alle Zeilen eingefügt, für die dies möglich ist. Die restlichen Zeilen werden verworfen und sy-subrc wird auf 4 gesetzt. Das Systemfeld sy-dbcnt wird auf die Anzahl der eingefügten Zeilen gesetzt.
D.h. es werden keine doppelten Zeilen erzeugt, was auch gar nicht möglich ist. D.h. ACCEPTING DUPLICATE KEYS erzeugt keinen Laufzeitfehler falls einzelne Datensätze bereits in der Datenbanktabelle vorhanden sind.

Eine einfache Möglichkeit zum Ausgeben der eingefügten Datensätze wäre die folgende:
Vor dem INSERT auszuführen:

Code: Alles auswählen.

SELECT sap_object, object_id, archiv_id, arc_doc_id
  INTO TABLE existing_entries
  FROM toa01
  FOR ALL ENTRIES IN @p_toa01
  WHERE sap_object = @p_toa01-sap_object
  AND object_id = @p_toa01-object_id
  AND archiv_id = @p_toa01-archiv_id
  AND arc_doc_id = @p_toa01-arc_doc_id.
 
 LOOP AT p_toa01 REFERENCE INTO DATA(archive_link).
   IF NOT line_exists( existing_entries[ sap_object = @p_toa01-sap_object object_id = @p_toa01-object_id archiv_id = @p_toa01-archiv_id arc_doc_id = @p_toa01-arc_doc_id ] ).
     INSERT archive_link INTO TABLE new_archive_link_entries.
   ENDIF.
 ENDLOOP. 
Die Tabelle new_archive_link_entries enthält dann alle Datensätze, die neu hinzugefügt werden sollen. Diese Tabelle könntest du alternativ im INSERT-Statement verwenden. Dann entfällt die Behandlung doppelter Datensätze.

Folgende Benutzer bedankten sich beim Autor jocoder für den Beitrag:
Sonne1234


Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von Tron (Top Expert / 1327 / 35 / 332 ) »
Hallo Julia.
Warum verwendest Du nicht den Baustein ARCHIV_CONNECTION_INSERT dafür ?
"Harte" Änderungen auf der DB sind eigentlich nicht so "beliebt" .

Code: Alles auswählen.

  DATA:
    lv_archiv_id  TYPE toav0-archiv_id,  " PI
    lv_arc_doc_id TYPE toav0-arc_doc_id, " 0050569B043C1EE99C9C9B7E1977F4A
    lv_ar_date    TYPE toav0-ar_date,    " sy-datum
    lv_ar_object  TYPE toaom-ar_object,  " FIOPAYAVIS
    lv_object_id  TYPE sapb-sapobjid,    " 1057000000082019
    lv_sap_object TYPE toaom-sap_object. " BKPF

  lv_archiv_id = s_toa-archiv_id. 
  lv_arc_doc_id = l_doc_id.    
  lv_ar_date = sy-datum.      
  lv_ar_object = s_toa-ar_object.  
  lv_object_id = s_toa-object_id.  
  lv_sap_object = s_toa-sap_object.

  CALL FUNCTION 'ARCHIV_CONNECTION_INSERT'
    EXPORTING
      archiv_id             = lv_archiv_id
      arc_doc_id            = lv_arc_doc_id
      ar_date               = lv_ar_date
      ar_object             = lv_ar_object
      object_id             = lv_object_id
      sap_object            = lv_sap_object
    EXCEPTIONS
      error_connectiontable = 1
      OTHERS                = 2.
gruß Jens

Folgende Benutzer bedankten sich beim Autor Tron für den Beitrag:
Sonne1234

<:: XING-Gruppe Tricktresor::>
Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen –
Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen.

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von DeathAndPain (Top Expert / 1933 / 252 / 410 ) »
Das ist allerdings richtig. Tabellen der SAP (also solche, deren Name nicht mit Z anfängt) darf man nur lesen. Ändern sollte man sie niemals! Der Hintergrund ist, dass Du niemals wissen kannst, welche technischen Querabhängigkeiten alles bestehen. Vielleicht muss eine Änderung in Tabelle A mit entsprechenden Änderungen in Tabelle B einhergehen oder darf aus Konsistenzgründen nur erfolgen, wenn Tabelle B entsprechende Werte enthält. Auch wenn Du glaubst, einen Zusammenhang verstanden zu haben, kannst Du Dir niemals sicher sein, da Du keinen Zugriff auf die SAP-internen Dokumentationen hast.

Im übrigen laufen harte Tabellenänderungen auch an den normalen Änderungsbelegen vorbei, die das SAP erzeugt. Sowas ist extrem unprofessionell.

Für fast alle Daten, die man sinnvollerweise ändern kann, gibt es Funktionsbausteine oder Methoden, die von der SAP zu diesem Zweck bereitgestellt werden. Diese sollte man immer nutzen! In den heutzutage extrem seltenen Fällen, dass es nichts Passendes gibt, kann man sich mit einem programmierten Batch Input behelfen. Wie das geht, würde hier allerdings den Rahmen sprengen.

Im übrigen zeigen die schlüsselverletzenden doppelten Einträge in Deiner internen Tabelle, dass deren Inhalt sogar schon den Primärschlüssel der von der SAP definierten Datenbanktabelle verletzt. Hier hast Du also schon den ersten Beweis, dass Deine Daten nicht konform zu den von der SAP definierten Konsistenzkriterien sind. In diesem Fall hat das ABAP-System Dich mit einem Dump gerettet. Sind die Daten aber nur inhaltlich und nicht technisch inkonsistent, wirst Du - zunächst - nichts merken. Im weiteren Verlauf wird es dann aber zu den komischsten Fehlern kommen, und zwar wenn Dein Programm längst geendet ist und die Leute im System weiterarbeiten.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
Sonne1234


Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von Sonne1234 (ForumUser / 30 / 17 / 2 ) »
Hallo Jens,

warum ich nicht den Baustein 'ARCHIV_CONNECTION_INSERT' verwendet habe - nun ja, weil er mir einfach nicht bekannt war und Google mir INSERT dtab rausgeworfen hat :D

Ich habe jetzt den Baustein verwendet. Könntest du nochmal einen Blick darauf werfen?

Code: Alles auswählen.

Loop at p_toa01 ASSIGNING <p_toa01>.

         CALL FUNCTION 'ARCHIV_CONNECTION_INSERT'
           EXPORTING
             ARCHIV_ID                   = 'FI'
             arc_doc_id                  = <p_toa01>-arc_doc_id
             AR_DATE                     = sy-datum
             ar_object                   = <p_toa01>-ar_object
*            DEL_DATE                    = ' '
*            MANDANT                     = ' '
             object_id                   = <p_toa01>-object_id
             sap_object                  = <p_toa01>-sap_object
             DOC_TYPE                    = 'PDF'
*            BARCODE                     = ' '
*            FILENAME                    = ' '
*            DESCR                       = ' '
*            CREATOR                     = ' '
          EXCEPTIONS
            ERROR_CONNECTIONTABLE       = 1
            OTHERS                      = 2.

         If sy-subrc = 0.
            <p_toa01>-znachricht = 'Verknüpfung erstellt.'.
  
         elseif
            sy-subrc <> 0.
            <p_toa01>-znachricht = 'Verknüpfung wurde nicht erstellt.Doppelter Eintrag?'.
         ENDIF.
         endloop.
Also diese Variante funktioniert auf jeden Fall. Aber ich bin mir manchmal irgendwie noch unsicher, ob ich wirklich einen LOOP benötige und ob ich diesen dann mit INTO oder ASSIGNING aufbauen sollte.

Außerdem würde ich am Ende wie gesagt, mein Ergebnis ausgeben. Also welche Belege sind verknüpft worden und welche nicht, sodass man diese ggf. nochmal überprüfen kann. Ich habe mir jetzt einfach ein Feld zur internen Tabelle hinzugefügt, sodass die Tabelle am Ende einfach ausgegeben werden kann.
Aber gibt es hier evtl. auch schönere Varianten?

Danke :)

Liebe Grüße
Julia

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von DeathAndPain (Top Expert / 1933 / 252 / 410 ) »
Zunächst, um einer Verwechslung vorzubeugen: Tron heißt Jens, und ich heiße Jens, aber wir sind unterschiedliche Jense. 😉

Mein SAP-Kurs in ArchiveLink ist doch geraume Zeit her, so dass ich zu dem Funktionsbausteinaufruf nichts sagen kann. Deine anderen Fragen aber kann ich beantworten.
Aber ich bin mir manchmal irgendwie noch unsicher, ob ich wirklich einen LOOP benötige
Überleg Dir, was Du zu finden erwartest: eine Zeile oder mehrere Zeilen.
  • Eine Zeile erwartest Du typischerweise dann, wenn Du zu einer Sache ein spezifisches Detail dazuliest. Wenn Du beispielsweise eine Materialnummer hast und die Materialbezeichnung dazu einliest oder eine Personalnummer hast und das Konzerneintrittsdatum dazuliest, dann kann es nur ein Ergebnis geben. Dann brauchst Du keinen LOOP, sondern es reicht ein ASSIGN mit entsprechenden Prüfungen auf Gleichheit in der eckigen Klammer.
  • Mehrere Zeilen erwartest Du beispielsweise dann, wenn Du zu einem Verkaufsauftrag alle Positionen einliest. Oder wenn Du zu einem Material alle Bestellungen einliest, auf denen jemals Exemplare davon bestellt worden sind. Das Stichwort lautet hier also "alle". Dann brauchst Du einen LOOP, weil Du dann mehrere Ergebnisse bekommen kannst.
  • Als Sonderfall brauchst Du auch einen LOOP, wenn eigentlich der erste Punkt vorliegt, Du die Suchbedingung aber nur per Ungleichheit formulieren kannst. Sowas ist aber sehr selten.
und ob ich diesen dann mit INTO oder ASSIGNING aufbauen sollte
LOOP INTO ist relativ veraltet; das braucht man eigentlich gar nicht mehr. ASSIGNING ist schneller, spart Speicher und erspart Dir MODIFYs und DATA-Deklarationen von Workarea-Feldern. ASSIGNING arbeitet direkt mit den Daten aus der Tabelle; INTO erzeugt eine Kopie davon. INTO würdest Du allenfalls dann brauchen, wenn Du den gelesenen Wert aus irgendeinem Grund nach dem Lesen verändern möchtest, ohne dass sich auch die entsprechende Zeile in der internen Tabelle ändern soll. Ein praktischer Anwendungsfall hierfür fällt mir allerdings nicht ein; ich habe schon seit Ewigkeiten keinen LOOP INTO mehr programmiert. An Feldsymbole muss man sich erst gewöhnen, aber dann sind sie viel eleganter als das Hantieren mit Workarea-Feldern.

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von Tron (Top Expert / 1327 / 35 / 332 ) »
Moin Julia.
Bei Funktionsbausteinen würde ich auf Literale verzichten und genau mit dem Datentyp übergeben , den der Baustein erwartet.
z.B.

Code: Alles auswählen.

  DATA:
    lv_archiv_id  TYPE toav0-archiv_id,  " PI
    lv_arc_doc_id TYPE toav0-arc_doc_id, " 0050569B043C1EE99C9C9B7E1977F4A
    lv_ar_date    TYPE toav0-ar_date,    " sy-datum
    lv_ar_object  TYPE toaom-ar_object,  " FIOPAYAVIS
    lv_object_id  TYPE sapb-sapobjid,    " 1057000000082019
    lv_sap_object TYPE toaom-sap_object, " BKPF
    lv_doc_type TYPE TOADV-DOC value 'PDF'.

Loop at p_toa01 ASSIGNING <p_toa01>.

  lv_archiv_id = 'FI'. 
  lv_arc_doc_id = <p_toa01>-arc_doc_id.    
  lv_ar_date = sy-datum.      
  lv_ar_object = <p_toa01>-ar_object.  
  lv_object_id = <p_toa01>-object_id.  
  lv_sap_object = <p_toa01>-sap_object.


  CALL FUNCTION 'ARCHIV_CONNECTION_INSERT'
    EXPORTING
      archiv_id             = lv_archiv_id
      arc_doc_id          = lv_arc_doc_id
      ar_date               = lv_ar_date
      ar_object            = lv_ar_object
*            DEL_DATE                    = ' '
*            MANDANT                     = ' '
      object_id              = lv_object_id
      sap_object            = lv_sap_object
      DOC_TYPE            = lv_doc_type
*            BARCODE                     = ' '
*            FILENAME                    = ' '
*            DESCR                       = ' '
*            CREATOR                     = ' '
          EXCEPTIONS
            ERROR_CONNECTIONTABLE       = 1
            OTHERS                      = 2.

         If sy-subrc = 0.
            <p_toa01>-znachricht = 'Verknüpfung erstellt.'.
  
"         elseif
"            sy-subrc <> 0.
          else.
            <p_toa01>-znachricht = 'Verknüpfung wurde nicht erstellt.Doppelter Eintrag?'.
         ENDIF.
         endloop.
Zum Thema Feldsymbole: Verwende ich grundsätzlich, wenn die interne Tabelle zu ändern ist, oder ich neues Coding schreibe. Ansonsten wäre mir der Aufwand zu groß alles umzustellen.

gruß Jens (Ach wie gut das niemand weiß .....)
<:: XING-Gruppe Tricktresor::>
Die deutsche Rechtschreibung ist Freeware, du darfst sie kostenlos nutzen –
Aber sie ist nicht Open Source, d. h. du darfst sie nicht verändern oder in veränderter Form veröffentlichen.

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von DeathAndPain (Top Expert / 1933 / 252 / 410 ) »
Bei Funktionsbausteinen würde ich auf Literale verzichten und genau mit dem Datentyp übergeben , den der Baustein erwartet.
Eine Philosophiefrage. Ich benutze gerne Literale, nicht nur weil es schnell geht, sondern weil ich sogar der Meinung bin, dass der Code bedeutend besser lesbar ist, wenn da konkret das steht, was übergeben werden soll und nicht nur ein ominöser Feldname, bei dem man erst ermitteln muss, was drin steht, nur um dann rauszufinden, dass es eh nur ein konstanter Wert ist, den man auch direkt hätte hinschreiben können. Wenn das Feld mehrfach verwendet wird und man die Möglichkeit sieht, dass irgendwann mal alles auf einen Schlag per Programmkorrektur auf einen anderen Wert umgestellt werden soll, hat so eine Variable vielleicht einen Vorteil. Diese Möglichkeit halte ist aber für sehr theoretisch. Für mich sind literalersetzende Felder in aller Regel nicht mehr als ein Wasserkopf.

Nach meiner Erfahrung führen die Verfechter der Nichtliteralsfraktion im wesentlichen rein akademische Gründe der Klasse "Das macht man einfach nicht, konstante Werte gehören nicht mitten in den Code." ins Feld. Diese Argumente kann ich für mich nicht akzeptieren, da ich sie als praxisfern wahrnehme und die Vermeidung von Literalen - abgesehen von der eben genannten Einschränkung - nach meiner Erfahrung nur Nachteile mit sich bringt. Etwas anderes ist es allenfalls, wenn es um einen Text geht, der potenziell in andere Sprachen übersetzt werden muss (je nach Anmeldesprache des Benutzers).

Aber, lieber Tron, Dein Beispiel ist auch nicht akademiekonform, denn da definiert man solche Felder auch technisch per CONSTANTS, und die Verfechter der ungarischen Notation weisen ihnen dementsprechend das Präfix lc_ statt lv_ zu.
Zum Thema Feldsymbole: Verwende ich grundsätzlich, wenn die interne Tabelle zu ändern ist, oder ich neues Coding schreibe. Ansonsten wäre mir der Aufwand zu groß alles umzustellen.
Womit Du implizit ausdrückst, dass Du auch keine Workareas mehr benutzt, wenn Du programmierst. Dass man nicht hektisch allen bestehenden Altcode ändert und sich bei der Gelegenheit ohne Not neue Programmierfehler einfängt, ist klar. Da sind wir einer Meinung.

Wenn die interne Tabelle nicht geändert werden soll, sind Feldsymbole aber genauso gut zu gebrauchen.
Zuletzt geändert von DeathAndPain am 13.02.2020 15:03, insgesamt 1-mal geändert.

Re: Füllen einer Datenbanktabelle mit INSERT anstatt MODIFY

Beitrag von qyurryus (Specialist / 112 / 84 / 45 ) »
Zum Thema Loops:
SAP selbst empfiehlt Feldsymbole (in der Regel), da am schnellsten:
https://github.com/SAP/styleguides/issues/115

Seite 1 von 1

Vergleichbare Themen

5
Antw.
9891
Views
INSERT / MODIFY auf Z-Tabelle mit/ohne Commit-Work ?
von gre » 19.11.2007 16:08 • Verfasst in ABAP® für Anfänger
2
Antw.
2360
Views
Datenbanktabelle auffüllen aus interner Tabelle mit Insert
von Nourie » 16.08.2005 15:29 • Verfasst in ABAP® für Anfänger
26
Antw.
20102
Views
Datenbanktabelle füllen
von Dyrdek » 04.06.2014 09:31 • Verfasst in ABAP® für Anfänger
4
Antw.
2250
Views
AS400 - Datenbanktabelle füllen
von sap_inchen » 10.04.2018 13:15 • Verfasst in ABAP® für Anfänger
9
Antw.
3117
Views
Füllen einer Datenbanktabelle mit den Daten aus der internen Tabelle
von Armin93 » 28.11.2019 10:15 • Verfasst in ABAP® für Anfänger

Newsletter Anmeldung

Keine Beiträge verpassen! Wöchentlich versenden wir lesenwerte Beiträge aus unserer Community.
Die letzte Ausgabe findest du hier.
Details zum Versandverfahren und zu Ihren Widerrufsmöglichkeiten findest du in unserer Datenschutzerklärung.