Code: Alles auswählen.
*&---------------------------------------------------------------------*
*& Report ZTEST4
*&---------------------------------------------------------------------*
REPORT ZTEST4.
DATA: BEGIN OF KUNDENSTAMM OCCURS 0,
KUNNR LIKE KNA1-KUNNR,
ADDRNUMBER LIKE ADR6-ADDRNUMBER,
END OF KUNDENSTAMM,
EMAIL LIKE ADR6-SMTP_ADDR.
* Hier muss die interne Tabelle KUNDENSTAMM mit den Kunden gefüllt werden, bei denen geprüft werden soll,
* ob es ihre Email-Adresse auch bei anderen Ansprechpartnern gibt.
LOOP AT KUNDENSTAMM.
SELECT SINGLE SMTP_ADDR INTO EMAIL FROM ADR6 AS X
WHERE ADDRNUMBER = KUNDENSTAMM-ADDRNUMBER
AND NOT EXISTS ( SELECT * FROM ADR6 WHERE ADDRNUMBER <> X~ADDRNUMBER
AND SMTP_ADDR = X~SMTP_ADDR ).
WRITE / EMAIL.
ENDLOOP.
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
ChrissixD
Code: Alles auswählen.
SELECT kunnr name1 ktokd adrnr INTO (dkunnr, dname, dgrup, kunadr)
FROM kna1
WHERE ktokd = '0001'.
SELECT smtp_addr INTO mail
FROM adr6
WHERE addrnumber = kunadr AND persnumber = ''.
SELECT SINGLE smtp_addr INTO mail
FROM adr6
WHERE persnumber NE '' AND addrnumber = kunadr AND smtp_addr = mail.
IF sy-subrc = 4.
WRITE: / dkunnr, dname.
WRITE: / mail.
WRITE: /.
ENDIF.
ENDSELECT.
ENDSELECT.
Dein Code wird im Prinzip funktionieren, auch wenn SELECT-ENDSELECT-Blöcke, obwohl meines Wissens nicht offiziell deprecated, als schlechter Stil angesehen werden. Üblich ist, eine passende interne Tabelle zu definieren, in die man mit dem ersten SELECT per Zusatz INTO TABLE die Ausgangszeilen reinfüllt, um anschließend darüber einen LOOP zu machen. Das ist performanter, als wenn Du Dir die Ergebniszeilen einzeln aus der Datenbank holst.Irgendwelche Anmerkungen dazu, was kann ich besser machen (Performance, Joins, usw.)?
Code: Alles auswählen.
SELECT KUNNR NAME1 KTOKD ADRNR SMTP_ADDR INTO (DKUNNR, DNAME, DGRUP, KUNADR, MAIL)
FROM KNA1
JOIN ADR6 ON ADR6~ADDRNUMBER = KNA1~KUNADR
AND ADR6~PERSNUMBER = SPACE
WHERE KTOKD = '0001'.
SELECT SINGLE SMTP_ADDR INTO MAIL
FROM ADR6
WHERE ADDRNUMBER = KUNADR
AND PERSNUMBER <> SPACE
AND SMTP_ADDR = MAIL.
CHECK SY-SUBRC = 4.
WRITE: / DKUNNR, DNAME.
WRITE / MAIL.
SKIP.
ENDSELECT.
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
ChrissixD
"SKIP." <---- <F1>ChrissixD hat geschrieben: Jetzt frage ich mich nur noch was das "SKIP." am Ende des Codes macht, weil das Programm ja beim Check schon aus der Schleife springt, wenn nichts gefunden wird
Syntax
SKIP { [n]
| {TO LINE line} }.
Varianten:
1. SKIP [n].
2. SKIP TO LINE line.
Wirkung
Positionierung des Listen-Cursors relativ zur aktuellen Zeile oder in einer beliebigen Zeile.
Variante 1
SKIP [n].
Wirkung
Diese Anweisung positioniert den Listen-Cursor relativ zur aktuellen Zeile. Die neue Zeile wird durch den Wert von n bestimmt. Für n wird ein Datenobjekt vom Typ i erwartet. Wenn der Wert von n kleiner oder gleich 0 ist, wird die Anweisung ignoriert. Wenn n nicht angegeben ist, wird die Anweisung so ausgeführt, als sei n mit dem Wert 1 gefüllt.
Die Positionierung erfolgt folgendermaßen:
• Wenn die Zeile des aktuellen Listen-Cursor durch eine Ausgabeanweisung (WRITE, ULINE) gesetzt wurde, wird der Listen-Cursor an die erste Stelle der Zeile gesetzt, die im Abstand von n Zeilen unter der aktuellen Zeile liegt.
• Wenn die Zeile des aktuelle Listen-Cursor durch eine Positionierungsanweisung (BACK, NEW-LINE, NEW-PAGE, SKIP) gesetzt wurde, wird der Listen-Cursor an die aktuelle Stelle der Zeile gesetzt, die im Abstand von n minus 1 Zeilen unter der aktuellen Zeile liegt.
Weiterhin gelten folgende Besonderheiten:
• Falls der Listen-Cursor nicht auf der aktuellen Seite positioniert werden kann, wird eine neue Seite erzeugt, wobei der eventuelle Seitenfuß der aktuellen Seite ausgegeben wird. Der Listen-Cursor wird in der ersten Stelle der ersten Zeile unter dem Seitenkopf der neuen Seite positioniert.
• Die Anweisung wird nur dann am Beginn einer Seite durchgeführt, wenn diese Seite die erste einer Listenstufe ist oder sie durch die Anweisung NEW-PAGE erzeugt wurde.
Hinweis
In den meisten Anwendungsfällen wirkt diese Variante der Anweisung SKIP einfach so, als würde sie n Leerzeilen erzeugen. Dabei ist aber zu beachten, dass solche Leerzeilen keinen Inhalt haben, der durch die FORMAT-Anweisung formatiert werden kann. Formatierbare Leerzeilen können nur durch die WRITE-Anweisung in Kombination mit SET BLANK LINES ON erzeugt werden.
Variante 2
SKIP TO LINE line.
Wirkung
Diese Anweisung positioniert den Listen-Cursor in der ersten Stelle der Zeile der aktuellen Seite, deren Nummer durch den Wert in line bestimmt wird. Für line wird ein Datenobjekt vom Typ i erwartet. Falls der Wert von line kleiner oder gleich 0 oder größer als die mit dem Zusatz LINE-COUNT der programmeinleitenden Anweisung bzw. NEW-PAGE definierten Seitenlänge in sy-linct ist, wird der Zusatz TO LINE ignoriert und stattdessen die Anweisung SKIP ohne Zusatz ausgeführt (siehe oben).
Hinweis
Wenn der Listen-Cursor mit SKIP TO LINE in die erste Listenzeile positioniert wird und die Liste einen Standardseitenkopf hat, werden die Ausgaben in die erste Zeile durch die Standardüberschrift überschrieben. Wenn mit SKIP TO LINE aber in die Zeilen von Seitenköpfen und Seitenfüßen positioniert wird, die zu TOP-OF-PAGE und END-OF-PAGE definiert wurden, werden die Seitenköpfe bzw. -füße überschrieben.
Beispiel
Die erste SKIP-Anweisung erzeugt beim Ereignis TOP-OF-PAGE eine Leerzeile. Die zweite SKIP-Anweisung positioniert den Listen-Cursor in dieser Zeile.
REPORT demo_skip NO STANDARD PAGE HEADING.
DATA sum TYPE i.
TOP-OF-PAGE.
SKIP.
ULINE.
START-OF-SELECTION.
DO 10 TIMES.
WRITE / sy-index.
sum = sum + sy-index.
ENDDO.
SKIP TO LINE 1.
WRITE: 'Numbers with sum' COLOR COL_HEADING,
sum COLOR COL_TOTAL.
Der SKIP ist nicht mehr und nicht weniger als eine schönere Variante DeinesJetzt frage ich mich nur noch was das "SKIP." am Ende des Codes macht
Na ja, der Primärschlüssel der Tabelle ist ja insbesondere auch ein Index. Einen Index zu nutzen ist offensichtlich sinnvoll, da das System sonst sequentiell durch die gesamte Datenbank rasen und jeden einzelnen Eintrag anschauen muss.Wie meinst du das mit den Schlüsselfeldern? Also das mit der richtigen Reihenfolge macht Sinn, aber sollte man immer alle Schlüsselfelder benutzen? Also in der Tabelle adr6 auch "Datum gültig von" und "Laufende Nummer"?
Ein weiterer Grund, zunächst einen SELECT INTO TABLE zu machen und dann per LOOP auf der internen Tabelle weiterzuarbeiten. Dann kannst Du diese nämlich rasch mitWie bekommt man es hin dass beim vergleichen der E-Mail im Select Single keine Groß- und Kleinschreibung beachtet wird?
Code: Alles auswählen.
LOOP AT kunden.
TRANSLATE kunden-email TO UPPER CASE.
MODIFY kunden.
ENDLOOP.
Damit ist man aber schon dicht am Hack, denn die genaue Syntax von Native SQL kann sich je nach Datenbank unterscheiden. Bei uns wurde vor einiger Zeit Oracle durch Sybase ausgetauscht, weil wir als HANA-Nutzer Sybase kostenlos benutzen dürfen, wohingegen Oracle ja fürstliche Lizenzgebühren zu nehmen pflegt. Wenn Du dann solch Kram in Deinen Programmen hast... ne, da arbeite ich lieber konservativ mit internen Tabellen, die ich mir mit dem TRANSLATE-Befehl passend zurechtwandle.Geht nicht direkt mit den Standardbefehlen von ABAP, sondern das ist der typische Anwendungsfall bei dem man darüber nachdenken kann, ob man sich nicht mit EXEC SQL vertraut machen sollte.
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag (Insgesamt 2):
ChrissixD • Somani