# [ORACLE] Demo: Datenbanklinks



## Exceptionfault (24. August 2005)

Gerade in großen Unnternehmen, mit verteilten Anwendungen und Standorten kommt es auch häufig zu verteilter Datenhaltung. In einem Standort sind Kundendaten, im nächsten wieder Lieferanten, und ganz wo anders Personaldaten. Was aber nun wenn man alle daten für eine Auswertung braucht ? 
Häufig gibt es dann komplizierte Schnittstellen über Export und Import. Das führt zu redundaten Daten, Übertragungsfehlern und aktuell sind die Daten schon gar nicht. Ein schönes Feature von Oracle um so etwas zu verhindern sind Datenbanklinks. Es ist also möglich von einer Datenbank aus auf eine entfernte Datenbank zuzugreifen und Daten auszutauschen. Das ganze lässt sich sogar transparent für Applikationen aufziehen, so dass eine Applikation z.B. auf 3 Datenbanken weltweit verteilt arbeitet. Mit einem stabilen und schnellen Netzwerk überhaupt kein Problem.

Nun, ein einfacher Datenbanklink zwischen 2 Oracle Datenbanken ist schnell erklärt:

```
CREATE PUBLIC DATABASE LINK MY_SND_DB
   CONNECT TO username
   IDENTIFIED BY "geHeiM" 
   USING 'MY_SND_DB';
```
Mit dem obigen Statement kann ich einfach einen Datenbanklink zu einer anderen Oracle Datenbank einrichten. Nutzen kann ich diesen Link dann etwa folgendermassen:

```
SELECT * FROM SALES@MY_SND_DB;
```
Mache ich aus dem obigen Statement eine View, merkt kein Mensch mehr, wo die Daten eigentlich stehen...

Mit dem @ hinter der Tabelle gebe ich also "den Ort" bekannt über welchen Link die Tabelle zu finden ist. Der Eintrag "USING 'xyz'" ist der Alias der Datenbank über den Oracle den Namen in eine Adresse und Port auflöst. MY_SND_DB muss also auf dem lokalen Server in der TNSNAMES.ORA gepflegt sein. CONNECT TO und IDENTIFIED BY geben den Benutzernamen und das Passwort an, mit dem ich mich an der fremden Datenbank anmelde. Das Passwort steht wohlgemerkt in " ", was unbedingt nötig ist, wenn es in meinem Passwort auf Groß- und Kleinschreibung ankommt.

Nun, das wars eigentlich schon fast zu Datenbank Links. Aber als Tutorial etwas mager, oder?
Deshalb dachte ich wir experimentieren ein bisschen und machen das selbe auch mal zwischen einer Oracle und einer NICHT Oracle Datenbank. Ja, das geht auch ;-)
Voraus muss ich sagen, ich habe das schon etliche male gemacht, zwischen diversen DB Systemen und Oracle, allerdings immer unter Windows. Zu Hause bin ich seit kurzem auf Linux und somit war es auch ein bisschen Neuland. Ich hab auch noch einen kleines Problem, aber unter Windows lief es bisher immer einwandfrei, daher denke ich wird das unter Linux auch noch klappen.

Ich hab mich für mySQL entschieden, damit können hier einige mehr anfangen ;-)

1.) Zunächst müssen wir den myODBC Treiber passend zu unserer mySQL Datenbank installieren. Was unter Windows simpel ist hat mich unter Linux gestern mehrere Stunden gekostet *g*. Und nach erfolgreicher Installation eine System DSN einrichten. Es sollte auf jeden Fall der Host (bei mir localhost), der User (bei mir kaiser) und die Datenbank (auch kaiser) in die Voreinstellung eingetragen werden. Ideallerweise sollte man die Connection dann auch mal testen, z.B. über MsQuery in Excel oder so. In meinem Beispiel heisst die DSN "myodbc", wie der Treiber... 

2.) Als nächstes müssen wir dem Listener auf unserem Oracle Server mitteilen welches Programm er zum connecten nutzen soll. Hierfür stellt Oracle das Tool "hsodbc" zur Verfügung. Es gibt auch "hsoledb" etc, aber mir hat odbc unter Linux erstmal genügt. Btw. HS steht für Heterogene Services.
Bei mir sah die Listener.ora (Pfad: $ORACLE_HOME/network/admin) nach der Konfiguration so aus (das fette ist neu, bodev ist meine lokale Oracle DB):

```
LISTENER =
 (DESCRIPTION_LIST =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = TCP)(HOST = sphinx.exceptionfault)(PORT = 1521))
   )
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = IPC) (KEY = BODEV))
   )
 )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = bodev.exceptionfault)
      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1)
      (SID_NAME = bodev)
    )
    (SID_DESC =
      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1)
      (SID_NAME = myodbc)
      (PROGRAM = hsodbc)
    )
  )
```
Den Listener müssen wir nach der Änderung neu starten, entweder über den Service unter Windows oder mit "lsnrctl reload".
Auch die TNSNAMES.ORA müssen wir anpassen und die fremde Datenbank bekannt machen:

```
bodev =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = bodev))
      (ADDRESS = (PROTOCOL = TCP)(HOST = sphinx.exceptionfault)(Port = 1521))
    )
    (CONNECT_DATA =
      (SID = bodev)
    )
  )

myodbc =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = sphinx.exceptionfault)(Port = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = myodbc)
    )
    (HS = OK)
  )
```
In meinem Fall, lag die mySQL DB auf dem selben Rechner, was jedoch nicht zwingend ist. Vergesst das "HS=OK" nicht, es kostet Stunden diesen Fehler zu suchen *g*.

Ein File fehlt jedoch noch: Zu finden im Verzeichnis $ORACLE_HOME/hs/admin liegt eine initHSODBC.ini. Davon machen wir eine Kopie und nennen sie nach dem Schema: init + DSN + ".ora". Bei mir also "initmyodbc.ora". Ich hab leider kein Configfile mehr von Windows, daher kann ich nicht genau sagen, welche der gleich folgenden Parameter für Windows nötig sind, aber ich glaube es müsste "HS_FDS_CONNECT_INFO" reichen.
Bei mir sah das File dann so aus:

```
HS_FDS_CONNECT_INFO = myodbc
HS_FDS_TRACE_LEVEL = 0
HS_FDS_SHAREABLE_NAME = /usr/lib/unixODBC/libmyodbc3-3.51.10.so
set ODBCINI=/etc/unixODBC/odbc.ini
```
Das wars sogar schon fast. Jetzt kann ich in Oracle meinen Datenbanklink anlegen. Als Parameter für USING einfach den Eintrag aus der TNSNAMES.ORA nehmen (myodbc, was sonst?!). Beim Zugriff auf mySQL muss man leider IMMER auf Groß- und Kleinschreibung achten, ansonsten schreibt Oracle alles groß. Daher muss z.B. auch der Username beim erstellen des Links in " ".
Beim Zugriff auf Tabellen macht dies das Statement etwas hässlich, aber es funktioniert:

```
sphinx:~ # mysql -u kaiser -p kaiser
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 16 to server version: 4.1.10a

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select * from users;
+-------+----------+----------+------------+-------+
| pk_id | username | password | last_login | email |
+-------+----------+----------+------------+-------+
|     1 | Andreas  | test     | 2005-08-24 | no    |
+-------+----------+----------+------------+-------+
1 row in set (0.03 sec)
mysql> exit
Bye

sphinx:~ # sqlplus /nolog

SQL*Plus: Release 10.2.0.1.0 - Production on Wed Aug 24 20:24:34 2005

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

SQL> conn / as sysdba
Connected.

SQL> create public database link myodbc connect to "kaiser" identified by "test" using 'myodbc';

Database link created.

SQL> desc "users"@myodbc
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 pk_id                                              NUMBER(10)
 username                                  NOT NULL VARCHAR2
 password                                  NOT NULL VARCHAR2
 last_login                                NOT NULL DATE
 email                                     NOT NULL VARCHAR2

SQL> select * from "users"@myodbc;

     pk_id username passw last_logi ema
---------- -------- ----- --------- ---
         1  Andreas  test 24-AUG-05  no
```

Einziges Problem: Man sieht, dass beim DESCRIBE keine Precision der VARCHAR2 Felder angegeben ist. Daher zeigt Oracle das Ergebnis leider etwas seltsam an. Da muss ich mal noch mit nem anderen ODBC Treiber experimentieren... aber soweit schonmal nicht schlecht, oder ? Achso, INSERT, DELETE etc... geht natürlich auch. Man darf eben nur keine Keywords von Oracle wie z.B. SYSDATE verwenden, da er ja die Statements an den mySQL Server weiterreit.


----------



## Thomas Darimont (24. August 2005)

Hallo!

 Danke dass du dir immer so viel Mühe gibst, war mal wieder Spitzenklasse!



> Deshalb dachte ich wir experimentieren ein bisschen und machen das selbe auch mal zwischen einer Oracle und einer NICHT Oracle Datenbank. Ja, das geht auch ;-)
> Voraus muss ich sagen, ich habe das schon etliche male gemacht, zwischen diversen DB Systemen und Oracle, allerdings immer unter Windows.


 Die Datenbank die innerhalb von MySQL für den DB-Link verwendet wird hast du ja sicherlich in der ODBC Datenquellendefinition angegeben. Kann man DB-Links auch ohne ODBC erstellen und wenn ja wie?
 Wie stelle ich es Beispielsweise an einen Link zwischen DB2 und Oracle herzustellen?
 Oder zwischen Oracle und Postgresql?
 Wohl gemerkt ohne ODBC. (wenn das geht ;-).

 Gruß Tom


----------



## Onkel Uwe (12. Juli 2007)

Das Tutorial ist ja schon etwas älter, aber ich habe genau damit gerade ein Problem. Ich möchte von einem Oracle XE auf einer Windows-Maschine auf eine MySQL DB auf einer Linux-Maschine zugreifen. ODBC ist eingerichtet und darüber bekomme ich grundsätzlich eine Verbindung zum Server. Die TNSNAMES und LISTENER.ora habe ich entsprechend editiert und diese werden auch verwendet (nach Listener-Log und Ausschrift tnsping).
(PROGRAM=hsodbc und HS=OK auch eingetragen; HSODBC ist auch installiert; Listener ist neu gestartet)
Nur scheint er nicht auf die init*.ora zuzugreifen. Ich habe zumindest trace_level =4 gesetzt und extra File angegeben, dieses wird jedoch nicht erstellt. Es kommt statt dessen bei tnsping zu einem "Fehler bei Paket-Prüfsumme" und nach Erstellung eines Datenbanklinks bei einem versuchten Zugriff zu einem Oracle-Fehler:


```
ORA-28545: Von Net8 bei der Verbindung zu einem Agenten diagnostizierter Fehler
Unable to retrieve text of NETWORK/NCR message 65535
ORA-02063: vorherige 2 lines von SDSN_TEST
```

Leider habe ich bisher noch keine Hinweise zu diesem Fehler gefunden...
Zu dem Fehler bei tnsping steht nur, dass man im Problemfall das tracing höher setzen soll, funktioniert ja nur leider überhaupt nicht 

Kann mir jemand sagen, wo der Fehler zu suchen sein kann?


----------



## MPr (12. Juli 2007)

in den MetaLinks findet man Note 423280.1: New Heterogeneous Services (HSODBC) Setup fails with ORA-28545 "Unable to retrieve text of NETWORK/NCR message 65535", die möglicherweise zum geschilderten Problem passt.

Dort gibt's folgende Erklärung:



> Cause:
> The (ORACLE_HOME =...) for the Heterogeneous Services entry does not point to the correct Oracle_Home.
> 
> Solution:
> ...



Gruß

MP


----------



## Onkel Uwe (12. Juli 2007)

Danke erstmal für die Antwort. Stellt sich mir die Frage, ob für HS ein anderes Home-Verzeichnis angegeben werden muss. Ich habe das Verzeichnis von den automatisch erstellten Einträgen her kopiert, welche aber nicht über HS laufen.
Der Pfad ist im Endeffekt: C:\oraclexe\oracle\product\10.2.0\server und darin befinden sich sowohl das NETWORK als auch das HS verzeichnis. HSODBC.exe ist im zugehörigen bin-Verzeichnis auch zu finden.
Unter dem Gesichtsounkt ist mir aber jetzt auch aufgefallen, dass der Autor des Tutorial dir Konfiguration wohl über das Tool hsodbc durchgeführt hat. Wenn ich dieses jedoch auf dem Server starte, wird nur kurz ein Eingabefenster geöffnet und das wars. Kein Konfigurationstool öffnet sich...

Des weiteren bin ich in der Zwischenzeit noch über zwei weitere Tutorials gestolpert:
Das eine sagt aus, dass für den tns-SERVICE_NAME SDSN_TEST als SID im Listener ODBCSDSN_TEST anzugeben sei und die init-Datei als initODBCSDSN_TEST.ora zu bezeichnen ist, der andere wie dieses Tutorial, dass SERVICE_NAME und SID gleich sein müssen, die init jedoch initHSSDSN_TEST.ora heissen soll.

Kann dort bestätigt werden, welche Form korrekt ist?

EDIT: Hat sich erledigt. Man sollte doch auf Deails achten. Dadurch, dass die DBs im Beispiel auf demselben Server lagen, hatte ich irgendwie mir eingebildet, der Eintrag in der TNSNAMES.ORA sollte auf den MySQL-Server gehen, was in dem Fall hier der selbe gewesen wäre. Richtig war natürlich, dass er auf den Oracle-Server verweisen muss, damit die nötigen Verbindungsdaten gefunden werden können. Jetzt klappt es...


----------



## newan (14. August 2008)

Nun muss ich das alte tutorial nochmal rauskramen und eine Frage stellen.

Ich habe den Datenbanklink hinbekommen und kann auch Tabellen selectieren. Nur sobald in der Tabelle ein varchar2 Feld vorkommt, erscheint die Fehlermedung:


```
ORA-00942: Tabelle oder View nicht vorhanden
[Generic Connectivity Using ODBC]
ORA-02063: vorherige 2 lines von MYSQLDB
```

Tabelle ist aber 100% da. Select stimmt auch inkl "".

Beispiel:
select id from "tab1"@mysqldb;

Wenn die Tabelle aus z.B. int Spalten besteht bekomme ich auf Oracleseite die Werte zurück (SQL+).

Kann mir jemand sagen wo ich den Fehler suchen kann?


----------



## heirobebe (12. Februar 2009)

Hallo,

ich habe einen Link auf eine DB2 Datenbank eingerichtet. Ich lasse mir über eine View eine Tabelle in DB2 anzeigen.

Allerding werden in Char-Feldern führende Blanks unterschlagen.

Kennt jemand dieses Problem?

Gruss
Robert


----------



## imma (5. Dezember 2014)

Hallo,
Wie kann ich eine Schnittstellen zwiechen Mysql und Oracle Datenbanken einrichten?
Ich arbeite mit Mysql Datenbank .
Ich möchte auf Daten von entfernete Oracle Datenbank zugreiffen und in Mysql Datenbank  laden.
Kann bitte mir jemand helfen?

Danke im Voraus
Imma


----------

