Kostenloses Tool um Daten aus der SAP Transaktion SE16 per BULK INSERT in den Microsoft SQL Server importieren

Für schnelle Instant-Reportings, die praktisch auf „Knopfdruck“ benötigt werden, besteht in großen Unternehmen durch Restriktionen der IT oft nicht die Möglichkeit über SAP Standardschnittstellen auf Funktionsbausteine oder BAPIs zuzugreifen. Benötigt man die Versorgung von SAP Stammdaten einer Nicht-SAP-Lösung, welche mit vorrübergehenden Inkonsistenzen betrieben werden kann, lassen sich Stammdaten über die Transaktion SE16 besorgen. Diese können anschließend in den Microsoft SQL Server übertragen werden.

Die Vorteile von replizierten Daten liegen auf der Hand:

  • Keine Belastung des SAP Systems. Der SQL Server übernimmt die Anfragelast.
  • Höhere Performance (vorhersehbare Leistungseinbrüche führen nicht zum Wegbrechen der Datenquelle, deshalb…)
  • Höhere Verfügbarkeit der Daten
  • Unsichere Daten (z.B. Personalinformationen) können von Stammdaten getrennt werden
  • Ein fachkundiger Anwender kann entscheiden ob bestimmte Daten, die z.B. für Kanbanzwecke/Lieferantenreportings (VMI)/… benötigt werden, im Internet verfügbar sein dürfen. Diese Daten könnten auf einen einfachen MS SQL Server in der DMZ repliziert werden.
  • Die Daten können über eine Web-Anwendung und eine beliebige Web-Technologie eingelesen werden. Ein Web-Entwickler hat die volle Kontrolle auf relationaler Ebene und kann genau bestimmen, was  mit den Daten geschieht (keine Seiteneffekte durch unbekannte Logik in den SAP-Funktionsbausteinen).

Herunterladen von SAP Stammdaten aus der Transaktion SE16

Als Anmeldesprache bitte Sicherheitshalber „DE“ benutzen

Schritt 1: Tabelle wählen
Schritt 1: Tabelle wählen
Zweiter Bildschirm SE16
Zweites Bild: Tabellen anzeigen mit SE16 (hier bitte die maximale Trefferzahl auf 9999999 erhöhen)
Schritt 3: Download im Kontextmenü
Schritt 3: Download im Kontextmenü
Schritt 4: Unkovertiert auswählen und Dateiname angeben
Schritt 4: Unkovertiert auswählen und Dateiname angeben

Hierfür wird die Transaktion SE16 zunächst aufgerufen (Berechtigungen müssen vorhanden sein) und die entsprechende Stammdatentabelle selektiert.

Interessante Tabellen für den Materialstamm sind:

  • MAKT (Materialtexte)
  • MARA
  • MARC
  • MARD
  • MPOP
  • ….

Nachdem die Liste angezeigt wird, öffnet man mit einem Rechtsklick auf der Tabelle das Kontext-Menü und wählt die Option „Download“.

Für einen schnellen Download wählen wir die Option „unkonvertiert“. Die Option „Tabellenkalkulation“ ist aufgrund älterer Office-Versionen nur für eine Datensatzmenge von 65000 Einträgen interessant.

Als Download-Ort nehmen wir C:\Temp\mattexte.txt . Öffnet man die Heruntergeladenen Daten erhält man ein scheinbar unmögliches Format der Form:

Tabelle:        MAKT
Angezeigte Felder:  5 von  5  Feststehende Führungsspalten:  3  Listbreite 0250
----------------------------------------------------------------------------------------------------------------------
| |MANDT|MATNR               |SPRAS|MAKTX                                   |MAKTG                                   |
----------------------------------------------------------------------------------------------------------------------
| |100  |00022837            |E    |Stoßdämpfer      3.8.01758              |Stossdaempfer    3.8.01758              |
| |100  |0-275-W-5-0-NAG     |E    |Wagenständer      275CM                 |Wagenstaender 275CM                     |

Durchforstet man die runtergeladene Datei, stellt man fest das der Header-Anteil öfter vorkommt, je mehr Datensätze man runtergeladen hat. Bei einer Menge ab 1000000 Stück wiederholt sich der Header regelmäßig und scheinbar willkürlich, so dass es schwer erscheint ein Import-Tool dafür zu implementieren.

Doch dieses Format lässt sich ohne Probleme mit dem vorgestelltem .NET-Programm in einer hohen Geschwindigkeit (1.000.000 Datensätze in 1 Minute)  in den Microsoft SQL Server importieren. Hierbei wird das „BULK INSERT“-Verfahren verwendet. Dabei wird nicht 1.000.000 Mal ein INSERT-Statement ausgeführt, sondern die Datei binär zum Server übertragen.

Hochladen der SAP-Stammdaten in den MS SQL Server

Schritt 1: Unkovertierte Datei aus SE16 wählen^
Schritt 1: Unkovertierte Datei aus SE16 wählen
Schritt 2: Datenbankverbindung einrichten, testen und Zieltabellenname wählen (Create Statement wird automatisch anhand des Headers in der Textdatei generiert)
Schritt 2: Datenbankverbindung einrichten, testen und Zieltabellenname wählen (Create Statement wird automatisch anhand des Headers in der Textdatei generiert)
Schritt 3: Weiter klicken für hochladen
Schritt 3: Weiter klicken für hochladen

DOWNLOAD DES KOSTENLOSES IMPORTERS VON SE16 ZU MS SQL SERVER

FluorineFX RTMP/Messaging konfigurieren

In einer Microsoft IIS Umgebung greift der Flex-Entwickler auf die kostenlose Middleware FluorineFX zurück. Hier gibt es 4 wichtige Dateien, die für die Konfiguration des Frameworks zuständig sind.

  • data-management-config.xml
  • messaging-config.xml
  • remoting-config.xml
  • services-config.xml

Dem Java-Entwickler sind diese Dateien ebenfalls aus der Java-Bibliothek BlazeDS bekannt.

Bei einem Kompiliervorgang wird die Datei services-config.xml in den Compilersettings angegeben.
[Rechtsklick auf Projekt in Workspace -> Properties -> Flex Compiler -> Additional compiler arguments]

-locale en_US -services services-config.xml -context-root /

Es gibt die Möglichkeit einen direkten Pfad mit einer Netzwerkfreigabe auf die services-config.xml des IIS-Servers anzugeben oder diese Datei lokal zu kopieren und die URL’s

  • RTMP – Real Time Messaging Protocol – was für Messaging benötigt wird und..
  • die normalen AMF Services (Actionscript Messaging Format – dient lediglich der RPC-Kommunikation wie GWT RPC oder SOAP Webservices, hierauf wird in diesem Artikel nicht eingegangen)

anzupassen. Hierbei kann man eine absolute Pfadangabe machen, wenn man den IIS nicht lokal auf dem Entwicklerrechner installiert hat (dies ist das Vorgehen in diesem Artikel). Auf dem Server, auf dem sich redundant (in der deployten FluorineFX-Anwendung im WEB-INF-Verzeichnis) diese Dateien befinden, werden allerdings entgegen den nachfolgenden Beispielen anstelle der absoluten Pfade die Platzhalter rtmp://{server.name}:2037 und http://{server.name}:{server.port}/{context.root}/Gateway.aspx verwendet.

services-config.xml:

<?xml version="1.0" encoding="utf-8" ?> 
<services-config>
    <services>
      <service-include file-path="remoting-config.xml" />
      <service-include file-path="messaging-config.xml" />
    </services>
       
    <channels>
        <channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
	        <endpoint uri="http://rechner3j.asag.asap.com:4321/Gateway.aspx" 
                 class="flex.messaging.endpoints.AMFEndpoint"/> 
        </channel-definition>

        <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
            <endpoint uri="rtmp://rechner3j.asag.asap.com:2037" 
             class="flex.messaging.endpoints.RTMPEndpoint"/>
            <properties>
                <idle-timeout-minutes>0</idle-timeout-minutes>
            </properties>
        </channel-definition>

    </channels>
</services-config>

remoting-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service id="remoting-service" class="flex.messaging.services.RemotingService" 
 messageTypes="flex.messaging.messages.RemotingMessage">
    <adapters>
        <adapter-definition id="dotnet" class="FluorineFx.Remoting.RemotingAdapter" 
	default="true"/>
    </adapters>

    <0default-channels>
        <channel ref="my-amf"/>
    </default-channels>

  <destination id="GenericDestination">
    <properties>
      <source>*</source>
    </properties>
  </destination>  

  <destination id="fluorine">
    <properties>
       <source>*</source>
    </properties>      
  </destination>
</service>

messaging-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<service id="message-service" class="flex.messaging.services.MessageService" 
 messageTypes="flex.messaging.messages.AsyncMessage">
     <!-- DO NOT CHANGE <adapters> SECTION-->
    <adapters>
	<adapter-definition id="messagingAdapter" 
        class="FluorineFx.Messaging.Services.Messaging.MessagingAdapter" 
        default="true"/>
    </adapters>

    <destination id="chat">
		<adapter ref="messagingAdapter"/>
    	<properties>
	        <network>
            	<session-timeout>0</session-timeout>
        	</network>
    	</properties>
    	<channels>
         	<channel ref="my-rtmp"/>
    	</channels>
    </destination>
</service>

FluorineFX geht folgendermaßen vor:
Sobald die Server-Seite (also nicht die Dateien mit den absoluten Pfaden wie obenstehend) mit der Definition für einen RTMP-Channel versehen wurde, wird ein Treffer auf einer beliebigen ASPX-Seite innerhalb der FluorineFX-Webanwendung dazu führen, das ein Socket auf dem definierten Port gestartet wird (oben wäre dass dann Port 2037 für RTMP). Ob es funktioniert hat, lässt sich mit einem telnet-Login prüfen. Hierzu einfach mal in der Eingabeaufforderung (CMD)

telnet hostname 2037

eingeben. Sollte der RTMP-Server nicht laufen, bitte mal auf dem Server per Remotekonsole einloggen und in der Eingabeaufforderung mit

telnet 127.0.0.1 2037

den Login versuchen.
Der Login funktioniert, wenn der Bildschirm gelöscht wird und ein Cursor in der Ecke links oben steht. Dieser Modus kann meistens mit STRG+C abgebrochen werden, sollte dies nicht funktionieren kann man auch die Eingabeaufforderung schließen.

Wichtig!!! Damit sie die Flex-Anwendung überhaupt mit der Messaging-Funktionalität und den obengenannten Konfigurationsdateien kompilieren können benötigen sie 2 Dateien, die sie in der Installation der Adobe Livecycle Services (LSDS) finden.

  • fds_rb.swc
  • fds.swc

Sie müssen einen Account bei Adobe registrieren und die LCDS runterladen, anschließend kopieren sie die o.g. Dateien in das LIB-Verzeichnis ihrer Flex-Anwendung und es kompiliert!!! Glückwunsch. So nun ein kleines Beispiel für einen gut funktionierenden Chat:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application creationComplete="{creationComplete()}" 
    xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
	<![CDATA[
	    import mx.controls.Alert;
	    import mx.rpc.events.FaultEvent;
            import mx.rpc.events.ResultEvent;
    	    import mx.messaging.*;
    	    import mx.messaging.messages.*;
    	    import mx.messaging.events.*;
    	    import mx.core.Application; 
    		
    	    public function creationComplete():void
    	    {
    		consumer.subscribe();
    	    }
   
            private function messageHandler(event:MessageEvent):void
            {
    		txtLog.text += event.message.body.toString()+'\r';
    	    }
   
            private function messagefaultHandler(event:MessageFaultEvent):void
    	    { 
        	Alert.show(event.faultString, "Error"); 
    	    }
   
            public function sendMessage():void
	    {
        	var message:AsyncMessage = new AsyncMessage();
       		message.body = txtOutput.text;
       		producer.send(message);
       		txtOutput.text="";
    	    }
	]]>
       </mx:Script>
       <mx:Consumer id="consumer" destination="chat" 
	   message="messageHandler(event)" fault="messagefaultHandler(event)"/>
       <mx:Producer id="producer" destination="chat" fault="messagefaultHandler(event)"/>
       <mx:VBox width="100%" height="100%">
    	
       <mx:HBox width="100%">
         <mx:TextInput width="100%" id="txtOutput"/>
         <mx:Button label="Skicka" click="sendMessage()"/>
       </mx:HBox>
    	<mx:TextArea height="100%" width="100%" editable="true" id="txtLog"/>
    </mx:VBox>
</mx:Application>