Hallo,
hier ein Paar kurze Anleitungen:
Symptom
Wie kann man über ABAP Sprachmittel aus einem auf Oracle basierenden R/3 System auf eine Tabelle zugreifen, die in einer anderen Oracle Datenbank liegt und die nicht unbedingt eine R/3 Datenbank zu sein braucht?
Weitere Begriffe
Database Link, Synonym, ORA-2068, ORA-2080, ORA-2081, abap/no_dsql95, dbs/ora/_retry_on_sql_error, ALTER SESSION
Ursache und Voraussetzungen
Oracle bietet die Möglichkeit, von einer Datenbank aus einen "Database Link" zu einer anderen Datenbank anzulegen und über diesen Database Link auf Tabellen der Remote Datenbank zuzugreifen. Dabei können nicht nur lesende, sondern auch schreibende Zugriffe auf Remote-Tabellen gemacht werden, wobei Oracle über ein 2-Phase Commit Protokoll die Synchronisation der verteilten Transaktion übernimmt.
Im folgenden werden Möglichkeiten beschrieben, wie Database Links aus dem R/3 heraus genutzt werden können.
Lösung
Ein Database Link kann auf der R/3 Datenbank durch folgendes Oracle Kommando angelegt werden:
CREATE PUBLIC DATABASE LINK <db_link>
CONNECT TO <user> IDENTIFIED BY <password>
USING '<connect_string>';
Was Sie hiebei als <connect_string> angeben müssen, entnehmen Sie bitte der Oracle Dokumentation.
Um nun von R/3 aus auf eine Remote-Tabelle zuzugreifen, gibt es zwei mögliche Alternativen:
1. Mit ABAP Open SQL
Hierfür ist die Beschreibung der Remote-Tabelle und ihrer Felder im R/3 Data Dictionary notwendig. In den Releases kleiner 3.x kann man eine Tabellenbeschreibung im Data Dictionary anlegen und aktivieren, ohne daß gleichzeitig auch die Tabelle auf der R/3 Datenbank angelegt wird. Ab Release 3.x wird jedoch beim Aktivieren die Tabelle implizit auf der R/3 Datenbank angelegt. In diesem Fall muß die angelegte Tabelle über das Datenbank-Utility wieder explizit gelöscht werden.
Anstelle der Tabelle legen Sie nun für die Remote-Tabelle ein Synonym unter dem im R/3 Data Dictionary verwendeten Tabellennamen an, also:
CREATE SYNONYM <table_name>
FOR [<user>.]<table_name>@<db_link>;
Über das Synonym kann nun mit dem vollen ABAP Open SQL Sprachumfang auf die Remote-Tabelle zugegriffen werden.
2. Mit ABAP Native SQL
Bei der Verwendung von Native SQL ist keine Tabellenbeschreibung im Data Dictionary erforderlich. Hier werden die Datentypen der im SQL-Statement angegebenen ABAP Variablen zugrunde gelegt. Diese sollten den Feldtypen der Remote-Tabelle entsprechen, d.h. für CHAR oder VARCHAR-Datentypen sollten Typ C Felder, für NUMBER Datentypen Typ I oder Typ P Felder als Host-Variablen im SQL-Statement verwendet werden.
Im Native SQL Statement kann der Database Link direkt angesprochen werden:
EXEC SQL.
SELECT ... FROM <table_name>@<db_link> ...
ENDEXEC.
Zur Vereinfachung der Schreibweise kann auch hier mit Synonymen gearbeitet werden, muß aber nicht.
Die Kommandos zum Anlegen eines Views oder eines Synonyms entnehmen Sie bitte den ORACLE-Handbüchern.
Mögliche Probleme:
1. ORA-2068 nach einem Durchstart der Remote-DB.
Aus Performance Gesichtspunkten werden SQL Statements im R/3 in einem Workprozeß-lokalen Statement Cache gepuffert. Bei mehrmaligem Aufruf desselben Statements kann dieses dann ohne Reparsing wieder ausgeführt werden. Dies bedeutet aber, daß für ein im Statement Cache befindliches SQL Statement die Verbindung zum Oracle Datenbank Prozeß über das Ausführungsende des Statements hinaus gehalten wird (technisch gesprochen wird der zugehörige DB-Cursor solange gehalten, bis das Statement aus dem Cache verdrängt wird).
Wenn nun ein SQL-Statement, das wie oben beschrieben über einen Database Link auf eine Remote-Tabelle zugreift, ausgeführt wird, dann landet dieses wie alle anderen SQL Statements auch im R/3 Statement Cache und der zugehörige DB-Cursor bleibt geöffnet. Wird nun die Remote-DB - aus welchen Gründen auch immer - durchgestartet und dasselbe Statement danach noch einmal ausgeführt, dann tritt der Oracle-Fehler ORA-2068 auf. Dies liegt daran, daß durch das Herunterfahren der Remote-DB der betreffende DB-Cursor ungültig wird, der R/3 Statement Cache dies aber nicht mitbekommt und deshalb immer wieder versucht, mit dem ungültigen DB-Cursor das Statement nochmals auszuführen.
Für R/3 Releases 3.0C und kleiner kann dieses Problem nur durch einen Durchstart des betroffenen Applikationsservers behoben werden.
Ab Release 3.0D kann dieses Problem beim Zugriff mit ABAP Open SQL dadurch umgangen werden, daß der R/3 Parameter
dbs/ora/_retry_on_sql_error = 2068
in allen Instanzprofilen gesetzt wird. Dieser Parameter bewirkt, daß beim Auftreten des Fehlers ORA-2068 der betreffende DB-Cursor geschlossen und für die Wiederausführung des Staments ein neuer DB-Cursor geöffnet wird. Dies geschieht implizit und somit transparent für das aufrufende ABAP Programm. Der Parameter zieht jedoch nicht bei Native SQL Zugriffen.
Bei der Verwendung von ABAP Native SQL für den Remote-Zugriff kann für die R/3 Releases 3.0D - 3.1I durch Setzen des R/3 Parameters
abap/no_dsql95 = NO
erzwungen werden, daß unmittelbar nach der Ausführung eines Native SQL Statements der verwendete DB-Cursor wieder geschlossen wird. Ab R/3 Release 4.x ist dieser Parameter nicht mehr erforderlich, da dort DB-Cursor bei Native SQL Statements immer sofort wieder freigegeben werden. In den Releases 3.0C und kleiner gibt es leider keine solche Möglichkeit.
Bitte verwenden Sie unbedingt den neuesten 3.1I Kernel, wenn Sie den Parameter abap/no_dsql95 setzen, da dort einige Native SQL betreffende Fehler korrigiert sind. Wie Sie den 3.1I Kernel einspielen entnehmen Sie bitte dem Hinweis 102445.
Aber auch wenn alle DB-Cursor geschlossen wurden, bricht wegen eines Oracle Fehlers in jedem Workprozeß der erste Zugriff über den Database Link mit dem Fehler ORA-2068 ab, nachdem die Remote-DB durchgestartet wurde. Vermutlich liegt dies daran, daß der dem R/3 Workprozeß zugeordnete Oracle Schattenprozeß, das "Ableben" des entsprechenden Schattenprozesses auf der Remote-DB nicht mitbekommt und deshalb den ersten Zugriff mit einem ORA-2068 quittiert. Danach baut er eine neue Verbindung zur Remote-DB auf und die weiteren Zugriffe werden korrekt ausgeführt. Als Workaround für dieses Oracle Problem wird im R/3 Kernel nun auch für ABAP Native SQL ein mit ORA-2068 abgebrochenes SQL-Statement implizit wiederholt. Diese Kerneländerung ist wirksam ab Patch-Level
4.0B: 650
4.5B: 404 (es genügt die Shared Library 'dboraslib.<ext>'
auszutauschen)
2. Ressourcenverbrauch auf der Remote-DB.
Ein weiteres Problem beim Zugriff über Database Links besteht darin, daß beim ersten Zugriff über den Database Link auf der Remote-DB ein Oracle (Schatten-)Prozeß gestartet wird. Dies gilt pro R/3 Workprozeß, d.h. wird das betreffende SQL Statement in mehreren R/3 Workprozessen ausgeführt, so werden auch ebensoviele Oracle Prozesse auf der Remote-DB gestartet. Diese Oracle Prozesse belegen auf der Remote-Maschine natürlich Resourcen (auch wenn sie nichts mehr tun) und werden deshalb vom DB-Administrator der Remote-DB u.U. nicht gerne über einen längeren Zeitraum gesehen.
Oracle bietet aus diesem Grunde die Möglichkeit Database Links explizit zu schließen und dadurch die auf der Remote-DB belegten Ressourcen wieder freizugeben. Das betreffende SQL Kommando lautet:
ALTER SESSION CLOSE DATABASE LINK <db_link>
Wird ein Remote-Zugriff nur gelegentlich durchgeführt, so ist es u.U. sinnvoll unmittelbar nach der Ausführung des SQL Statements den dadurch geöffneten Database Link wieder zu schließen. Allerdings erlaubt Oracle die Ausführung des obigen Befehls nur dann, wenn die DB-Transaktion, innerhalb derer der Remote-Zugriff erfolgte, committet und die zugehörigen DB-Cursor geschlossen wurden. Andernfalls führt der Versuch, den Database Link zu schließen, zu den Oracle Fehlern ORA-2080 oder ORA-2081.
Dieses Problem kann beim Remote-Zugriff über ABAP Open SQL leider nicht umgangen werden, da es momentan keine Möglichkeit gibt, das Schließen eines DB-Cursors nach der Ausführung eines Open SQL Statements im R/3 Statement Cache zu erzwingen. Dies bedeutet, daß der Database Link in diesem Fall vom ABAP Programm heraus nicht mehr geschlossen werden kann. Die auf der Remote-DB belegten Ressourcen bleiben so lange bestehen, bis der betreffende R/3 Workprozeß beendet oder die Remote-DB heruntergefahren wird.
Wenn die Remote-Zugriffe ausschließlich über ABAP Native SQL erfolgen, die DB-Cursor also unmittelbar nach Ausführung des SQL Statements wieder geschlossen wurden, dann können Database Links im ABAP Programm auch explizit wieder geschlossen werden:
....
EXEC SQL.
SELECT .... FROM <table>@<db_link> ...
ENDEXEC.
....
EXEC SQL.
COMMIT
ENDEXEC.
* Das Commit ist erforderlich, da der Database Link sonst
* nicht geschlossen werden kann (ORA-2080)
EXEC SQL.
ALTER SESSION CLOSE DATABASE LINK <db_link>
ENDEXEC.
* Nun sind die Ressourcen auf der Remote-DB wieder freigegeben
Reparaturen im Coding
-------------------------------------------------------------------------------------------
database link Beispiel !!!!!!!!!!!!!!!!!
zunächst tnsnsamesora die SID bekannt machen !
danach testen :
mit Befehl: tnsping HRT_ALT
nun die Realisierung:
sqlpus
enter user-name: / as sysdba
sql> create public database link HRT_ALT connect to sapr3 identified by sap using 'HRT_ALT';
sql> select count (*) from atab@hrt_alt;
--------------------------------------------------------------------------------------------
Beispiel Datenbank auf der nt4-qsys:
user: qsys604 passw: qsys
hier Auszug der tnsnames.ora der Datenbank QSYS
PROD.WORLD =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = nt4-qsys)(Port = 1521))
(ADDRESS = (COMMUNITY = tcp.world)(PROTOCOL = TCP)(Host = nt4-qsys)(Port = 1526))
)
(CONNECT_DATA = (SID = ORCL))
)
Bekanntmachung dieser Deklarierung auf R3INT (tnsnames.ora)
nun testen:
auf R3INT:
svrmgrl connect system/manager@PROD
------------
jetzt nur auf die Datenbank von R3INT anmelden und ein Databaselink erzeugen:
Beispiel:
create public database link QSYS connect to qsys604 identified by qsys using 'PROD';
select count (*) from artikel@QSYS;
----------------------------------------------------------------------------------------------
nun zunächst die tabelle löschen!
-drop table sapr3.lge_stamm
jetzt Synonym auf der R/3 Datenbank erzeugen:
Beispiel:
create synonym sapr3.zlge_stamm for qsys604.lge_stamm@QSYS;
Prüfung mit:
desc sapr3.zlge_stamm;
------------------------------------------------------------------------------------------------
Nun kann über ABAP auf die Tabelle zugegriffen werden!
Hierzu ein Beispielprogramm:
REPORT ZDBLINKQSYS .
TABLES: ZLGE_STAMM.
SELECT * FROM ZLGE_STAMM.
write: / ZLGE_STAMM-NLGEKEN,ZLGE_STAMM-SLGEKURZ,ZLGE_STAMM-SLGEBEZ.
ENDSELECT.
Gruß
didisap