Warum wird bei meinem INSERT nur ein Feld gefüllt?

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

Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Sonne1234 (ForumUser / 30 / 16 / 1 ) » 17.01.2020 10:39

Hallo zusammen,

ich möchte aus meiner internen Tabelle in eine transparente eigene Tabelle schreiben. Aber irgendwie wird nicht die Zeile übernommen, sondern nur das erste Feld.

Code: Alles auswählen.

 LOOP AT p_table ASSIGNING FIELD-SYMBOL(<p_table>).

    SELECT objky kschl erdat vstat parnr
           INTO CORRESPONDING FIELDS OF TABLE p_nast
           FROM nast  
           WHERE objky EQ <p_table>-vbeln AND 
                      kschl EQ 'X'.

    IF sy-subrc NE 0.
      INSERT ZFI_FEHLER FROM <p_table>.
    ENDIF.
Wenn in der NAST Tabelle für eine Zeile aus p_table kein Eintrag gefunden wird, soll die gesamte Zeile in meine erstellte Z-Tabelle ZFI_FEHLER übernommen werden. Die Felder sind eigentlich komplett identisch. Aber irgendwie wird nur das Feld VBELN übernommen. Die anderen drei Felder bleiben leer.

Habt ihr eine Idee, woran das liegen könnte?

Vielen Dank und lieben Gruß
Julia
Zuletzt geändert von Sonne1234 am 17.01.2020 12:04, insgesamt 2-mal geändert.


Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Tron (Top Expert / 1129 / 18 / 250 ) » 17.01.2020 11:52

Moin.
Wie ist denn der Return code nach dem INSERT ?
Vielleicht fehlt auch nur der COMMIT WORK.
gruß Jens
<:: 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: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Sonne1234 (ForumUser / 30 / 16 / 1 ) » 17.01.2020 11:56

Hallo Jens,

Wenn ich jetzt alles richtig gemacht habe, wird sy-subrc mit Null ausgegeben. Es werden ja auch die Werte in der Tabelle erfasst. Nur eben nicht alle Werte.

Hast du noch eine Idee?

Gruß Julia

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von DeathAndPain (Top Expert / 1271 / 139 / 291 ) » 17.01.2020 12:20

Obwohl ein COMMIT WORK guter Stil ist, ist er nach meiner Erinnerung nicht zwingend erforderlich. Wenn das Programm endet, ohne dass es einen ROLLBACK gegeben hat, committed das System nach meiner Erinnerung automatisch. Habe ich aber lange nicht mehr untersucht, da ich immer COMMITte.

Ansonsten fehlt bei dem Beispielcode wieder die Typisierung, insbesondere der internen Tabelle p_table und der Datenbanktabelle ZFI_FEHLER. Vor allem der Tabellenschlüssel ist da auch interessant.

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von gtoXX (Specialist / 124 / 26 / 18 ) » 17.01.2020 12:25

Frage : Sind die Felder überhaupt in <p_table> gefüllt ?

Ich hoffe aufgrund der Namensgebungen, das ist nur ein Spielprogramm.
"Code lügt nicht ^^"

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Sonne1234 (ForumUser / 30 / 16 / 1 ) » 17.01.2020 13:04

Hallo zusammen,

so hier nochmal der Code mit den Typisierungen. Ich hoffe, dass beim Kopieren nun nichts verloren gegangen ist.

Code: Alles auswählen.

types:BEGIN OF ty_vbrk,
         vbeln TYPE c LENGTH 30,
         fkart TYPE vbrk-fkart,
         fkdat TYPE vbrk-fkdat,
         rfbsk TYPE vbrk-rfbsk,
       END OF ty_vbrk.

TYPES: tty_vbrk  TYPE TABLE OF ty_vbrk,
           tty_nast  TYPE TABLE OF ty_nast.

data: gt_nast TYPE tty_nast,
gt_sap TYPE tty_vbrk.

PERFORM f_nast USING gt_sap CHANGING gt_nast.

FORM f_nast

  USING p_table TYPE tty_vbrk CHANGING p_nast TYPE tty_nast.

  LOOP AT p_table ASSIGNING FIELD-SYMBOL(<p_table>).

    SELECT objky kschl erdat vstat parnr
           appending CORRESPONDING FIELDS OF TABLE p_nast
           FROM nast
           WHERE objky EQ <p_table>-vbeln AND
                 kschl EQ 'X'.

    IF sy-subrc NE 0.
      INSERT zfi_fehler from <p_table>.
    ENDIF.

  ENDLOOP.
ENDFORM. 
Die Tabelle ZFI_FEHLER hat die folgenden Felder mit dem jeweils zugehörigen Datenelement:

VBELN VBELN
FKART FKART
FKDAT FKDAT
RFBSK RFBSK

Schlüsselfelder sind hierbei alle Felder. Benötigt ihr hier noch weitere Informationen, um das beurteilen zu können?

Das Feld VBELN hat in der Tabelle ZFI_FEHLER eine Länge nur von 10. Alle anderen Felder sind gleichlang. Aber genau dieses Feld wird ja trotz der unterschiedlichen Definition gefüllt. Alle anderen Felder, die für mich gleich aussehen, werden nicht gefüllt.

Danke nochmal für eure Hilfe

Gruß
Julia

Folgende Benutzer bedankten sich beim Autor Sonne1234 für den Beitrag:
Ichse2 (17.01.2020 13:53)


Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von A6272 (Specialist / 136 / 1 / 14 ) » 17.01.2020 13:51

Hallo,

wieviele Einträge sind denn in gt_sap = p_table?
Sind in DB-Tabelle nast einträge die zu gt_sap passen?

was liefert denn der sy-subrc vor! und nach "INSERT zfi_fehler"?

Grüße
Alex

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von DeathAndPain (Top Expert / 1271 / 139 / 291 ) » 17.01.2020 13:56

Das Feld VBELN hat in der Tabelle ZFI_FEHLER eine Länge nur von 10. Alle anderen Felder sind gleichlang. Aber genau dieses Feld wird ja trotz der unterschiedlichen Definition gefüllt. Alle anderen Felder, die für mich gleich aussehen, werden nicht gefüllt.
Trotzdem ist genau das die Ursache. Wenn Du einen INSERT zfi_fehler from <p_table>. machst, dann beachtet er keine Unterfeldgrenzen, sondern schreibt Byte für Byte den Inhalt von <p_table> in die Datenbankzeile. Das geht schief ab dem ersten Feld, dessen Länge nicht übereinstimmt. Bei Dir ist das gleich das allererste Feld.

Ich verstehe auch nicht, weshalb Du ein Feld VBELN nennst und dann aber anders definierst als den echten Datentyp von VBELN, obwohl Du sogar Inhalte von Typ VBELN da reinfüllen möchtest. Abgesehen davon, dass es in Deinem Fall nicht funktioniert (was man aber mit ein paar syntaktischen Kunstgriffen sicherlich hinkriegen würde), führst Du damit jeden Leser Deines Codes auf's Glatteis und erzeugst unprofessionellen Chaoscode.

Bitte sag uns, was Du Dir dabei gedacht hast, in Deinem Typ ty_vbrk das Feld VBELN mit 30 Zeichen zu definieren. Dann können wir Dir Vorschläge machen, wie man Dein Ziel auf programmtechnisch saubere Weise erreichen kann.

Beachte bitte auch die Seitenbemerkung von gtoXX. Feldnamen sollten aussagekräftig sein hinsichtlich ihres Inhalts. P_TABLE ist insofern ein ganz miserabler Feldname, weil man außer der Tatsache, dass es sich dabei um ein Tabellenfeld handelt (was schon aus der Typisierung hervorgeht), null Informationen darüber bekommt, welchen Inhalt dieses Feld aufnehmen und welchem Zweck es dienen soll. Die Folgen bekommst Du schon hier im Forum zu spüren, denn anstatt Deinem Code einfach anzusehen, wo Du hinwillst, müssen wir rätselraten und können Dir daher bislang nur Tipps zu syntaktischen Fehlern geben. Wäre Dein Code syntaktisch fehlerhaft, aber von den Benamungen sprechend, dann hätte schon längst jemand gesagt, wie Du das bekommst, was Du eigentlich haben möchtest, denn dann würde man es "sehen".

Übrigens hält auch die SAP sich an das Prinzip, Variablennamen sprechend zu wählen, nur dass die hiesigen Feldnamen aus einer alten Zeit stammen, bei der noch jedes Byte kostbar war, so dass die SAP sich für ihre Standardfeldnamen auf fünf Zeichen Länge festgelegt hat. Dadurch sind die meisten ihrer Feldnamen Abkürzungen. Aber VBELN steht beispielsweise für "Vertriebsbelegnummer". Bei diesem Wort hat man sofort eine Vorstellung, was da für Werte drin sein werden. Stell Dir mal vor, die SAP hätte das Feld stattdessen FDL10 (für "Feld der Länge 10") genannt! Dann hast Du eine Vorstellung, was Du tust, wenn Du Dein Feld P_TABLE nennst.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag (Insgesamt 4):
jocoder (17.01.2020 14:11) • abuma (17.01.2020 14:34) • Sonne1234 (17.01.2020 16:35) • Legxis (17.01.2020 16:49)


Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Sonne1234 (ForumUser / 30 / 16 / 1 ) » 17.01.2020 17:00

Hallo zusammen,

erstmal nochmal vielen Dank für eure Hilfe, insbesondere DeathAndPain.

Das mit dem "unprofessionellen Chaoscode" hast du schön gesagt. :D Leider ist da wohl auch sehr viel wahres dran. Aber mir fehlt wohl manchmal so eine Art Mentor, der kontrolliert und Tipps gibt. Deshalb bin ich auch sehr froh darum, dass ihr mir so eine große Hilfe seid :)

In diesem Fall konnte ich das Feld einfach umstellen und es scheint alles zu funktionieren. Den Grund, warum ich das Feld umdefiniert habe, kann ich euch aber an einem anderen Beispiel zeigen.

Ich selektiere z. B. Daten aus einer Datenbanktabelle und aus meiner daraus resultierenden internen Tabelle möchte ich, weitere Daten aus einer anderen Datenbanktabelle selektieren:

Code: Alles auswählen.


BEGIN OF ty_bkpf,
         bukrs TYPE bkpf-bukrs,
         blart TYPE bkpf-blart,
         bldat TYPE bkpf-bldat,
         budat TYPE bkpf-budat,
*         xblnr TYPE c LENGTH 10,
         xblnr type bkpf-xblnr,
        END OF ty_bkpf,

BEGIN OF ty_vbrk,
         vbeln type vbrk-vbeln,
         fkart TYPE vbrk-fkart,
         fkdat TYPE vbrk-fkdat,
         rfbsk TYPE vbrk-rfbsk,
       END OF ty_vbrk.

DATA: gt_bkpf TYPE STANDARD TABLE OF ty_bkpf,
          gt_vbrk TYPE STANDARD TABLE OF ty_vbrk.


SELECT bukrs blart bldat budat xblnr 
          FROM bkpf
          INTO CORRESPONDING FIELDS OF TABLE gt_bkpf
          WHERE bukrs IN so_bukrs AND
                blart IN so_blart AND
                cpudt IN so_cpudt AND
                awtyp IN so_awtyp.

  SELECT vbeln fkart fkdat rfbsk
           INTO CORRESPONDING FIELDS OF TABLE gt_vbrk
           FROM vbrk FOR ALL ENTRIES IN gt_bkpf
           WHERE vbeln EQ gt_bkpf-xblnr.
  ENDIF.
Wenn ich den Code nun so lasse, wie er hier gezeigt wird, erhalte ich die folgende Fehlermeldung:
"Bei Verwendung des Zusatzes "FOR ALL ENTRIES IN itab" müssen die Felder "VBELN" und "GT_BKPF-XBLNR" gleichen Typ und gleiche Länge haben."

Tja und da dachte ich mir, da mache ich mir die Felder doch gleich :D (s. den Teil, den ich ausgesternt habe) Ist vermutlich wirklich schlampiges programmieren, aber es hat zu dem Ergebnis geführt, dass ich brauchte. Für mich war das in dem Moment die einfachste Lösung. Das solche Deklarierung evtl. an späterer Stelle zu Problemen führen, habe ich nicht bedacht.

Vielleicht habt ihr hier ja noch eine bessere Lösung für mich.

Und bzgl. der Namensgebung habt ihr auch Recht. Ich werde zukünftig sprechendere Namen verwenden. Ich bin da glaube nur von mir ausgegangen. Ich selber weiß ja, was in der Tabelle stehen soll.

Danke euch :) und einen schönen Abend
Gruß Julia

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von DeathAndPain (Top Expert / 1271 / 139 / 291 ) » 18.01.2020 10:21

Das von Dir geschilderte Problem kann ich nachvollziehen und sehe zwei Lösungen dafür:

a) Du baust Dir eine temporäre Hilfstabelle mit dem benötigten Feldtyp auf:

Code: Alles auswählen.

DATA xblnr_as_vbeln TYPE STANDARD TABLE OF vbeln WITH EMPTY KEY.

SELECT bukrs blart bldat budat xblnr 
          FROM bkpf
          INTO CORRESPONDING FIELDS OF TABLE gt_bkpf
          WHERE bukrs IN so_bukrs AND
                blart IN so_blart AND
                cpudt IN so_cpudt AND
                awtyp IN so_awtyp.

xblnr_as_vbeln = VALUE #( FOR <zeile> IN gt_bkpf ( CONV vbeln( <zeile> ) ).

SELECT vbeln fkart fkdat rfbsk
         INTO CORRESPONDING FIELDS OF TABLE gt_vbrk
         FROM vbrk FOR ALL ENTRIES IN xblnr_as_vbeln 
         WHERE vbeln EQ xblnr_as_vbeln-table_line.

FREE xblnr_as_vbeln.
Das kostet kaum Performance. Allemal weniger, als Du mit dem FOR ALL ENTRIES IN durch Entlastung der Datenbank gewinnst. (Habe ich jetzt so nicht getestet, u.U. ist bei der Syntax des FOR noch Feintuning nötig, da xblnr_as_vbeln eine Tabelle ohne Struktur ist, aber in etwa so sollte es gehen.)

b) Du benutzt INTO CORRESPONDING FIELDS OF TABLE anstelle von INTO TABLE. Damit weist Du den SELECT an, nicht einfach den Inhalt der Tabellenzeile ohne Beachtung von Feldgrenzen in die Zeilen Deiner Zieltabelle zu klatschen, sondern Spalte für Spalte anhand des Namens zu übertragen. Ist geringfügig weniger performant als INTO TABLE, hat dafür aber den Vorteil, in Deinem Fall zu funktionieren. 😉

Auf jeden Fall aber solltest Du den Spaltennamen Deiner internen Tabelle so nennen, wie er typisiert ist. Bei Lösung b) würde ein Programmierer dann sehen, dass Du ein Feld des Typs xblnr in eine Spalte des Typs vbeln übertragen lässt. Allerdings könnte das dazu führen, dass Lösung b) nicht funktioniert, da der CORRESPONDING sich an den Spaltennamen orientiert. In dem Fall würde ich aber lieber auf Lösung a) setzen, als Pfusch zu machen.

(Ich bin jetzt grad nirgends eingeloggt und kann daher nicht nachprüfen, ob xblnr und vbeln nicht ohnehin gleich typisiert sind, so dass es in diesem Fall egal wäre. Aber wir reden hier ja über das Prinzip.)

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
Sonne1234 (18.01.2020 12:32)


Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von Sonne1234 (ForumUser / 30 / 16 / 1 ) » 18.01.2020 12:32

Hallo,

vielen Dank für deine ausführliche Antwort. Ich muss aber doch nochmal etwas nachfragen.

Wenn ich das Coding genauso, wie von dir unter a beschrieben, aufbaue, wird anschließend leider nichts mehr selektiert.

XBLNR_AS_VBELN erhält dann die Werte Buchungskreis und Belegnummer. Das sind die beiden Felder, die in meiner Tabelle gt_bkpf als erstes definiert worden sind.

Wenn ich XBLNR an den Anfang der Definition meiner gt_bkpf setze, klappt alles wie gewünscht.
Aber ich kann doch im Coding auch bestimmt festlegen, dass ich die Deklaration meiner Tabelle gt_bkpf nicht anpassen muss, oder?

Vielen Dank.
Gruß Julia

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von gtoXX (Specialist / 124 / 26 / 18 ) » 18.01.2020 21:15

Mit ( CONV vbeln( <zeile> ) ) wird einfach der Inhalt von Zeile übertragen Und zwar so lang wie das Zielfeld ist.

Code: Alles auswählen.


DATA xblnr_as_vbeln TYPE STANDARD TABLE OF vbeln WITH EMPTY KEY.

Finde ich von der Benamung her ungünstig. tab_vbeln

DATA tab_vbeln TYPE STANDARD TABLE OF vbeln WITH EMPTY KEY.

tab_vbeln = VALUE #( FOR <zeile> IN gt_bkpf ( CONV vbeln( <zeile>-xblnr ) ).

Es fehlte das -xblnr um das korrekte Feld anzusprechen.

----

Du kannst auch gleich einen Join verwenden, wenn du die Werte aus gt_bkpf nicht brauchst .

SELECT v~vbeln, v~fkart, v~fkdat, v~rfbsk
   FrOM bkpf AS b
   INNER JOIN vbrk as v ON vbeln = b~xblnr
   INTO TABLE @DATA(tab_vbrk)
   WHERE b~bukrs IN @so_bukrs AND
         b~blart IN @so_blart AND
         b~cpudt IN @so_cpudt AND
         b~awtyp IN @so_awtyp.

Mit @DATA(tab_vbrk) wird dir eine Tabelle aufgebaut mit den 4 selektierten Felder. Eine separate Typdeklaration ala ty_vbrk ist nicht nötig.

Folgende Benutzer bedankten sich beim Autor gtoXX für den Beitrag:
Sonne1234 (20.01.2020 11:42)

"Code lügt nicht ^^"

Re: Warum wird bei meinem INSERT nur ein Feld gefüllt?

Beitrag von DeathAndPain (Top Expert / 1271 / 139 / 291 ) » 20.01.2020 09:11

Wenn ich das Coding genauso, wie von dir unter a beschrieben, aufbaue, wird anschließend leider nichts mehr selektiert.

XBLNR_AS_VBELN erhält dann die Werte Buchungskreis und Belegnummer. Das sind die beiden Felder, die in meiner Tabelle gt_bkpf als erstes definiert worden sind.
Mir ist da ein kleiner Fehler unterlaufen, der sich bei Verwendung der (an sich hervorragenden) 7.40-Notation gerne mal einschleicht:

xblnr_as_vbeln = VALUE #( FOR <zeile> IN gt_bkpf ( CONV vbeln( <zeile>-xblnr ) ).

Du willst ja nicht die gesamte Zeile von gt_bkpf in xblnr_as_vbeln übernehmen, sondern nur die xblnr. Ergänze den oben rot hervorgehobenen Teil, dann sollte es gehen.

Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
Sonne1234 (20.01.2020 11:40)


Seite 1 von 1