5 Minuten Lesezeit (1091 Worte)

PowerShell und Oracle - ein gutes Team

Ich nutze fast täglich PowerShell zum Zugriff auf Daten in Oracle-Datenbanken. Warum gerade in dieser Kombination will ich anhand von einem Beispiel vorstellen. Vorab wird es aber auch ein paar Worte zur verwendeten Technik geben. 

Warum PowerShell? 

Ganz einfach: Weil es da ist. Ganz ohne die Installation von zusätzlichen Komponenten ist PowerShell auf jedem Windows-System vorhanden. Das ist gerade bei meinen Kunden wichtig, nicht immer kann ich mir die Installation von zusätzlicher Software wünschen. 

Die verwendete Technik 

Ich nutze die von Oracle bereitgestellte Bibliothek „Oracle.ManagedDataAccess.dll", die auf vielen Systemen als Teil des Oracle Clients schon installiert sein dürfte. Sie befindet sich im Pfad „odp.net\managed\common“ unterhalb des Oracle Home. Falls nicht, kann diese Bibliothek auch als Teil des NuGet-Paketes „Oracle.ManagedDataAccess" heruntergeladen werden. Eine Installation ist nicht notwendig. Das von der Webseite heruntergeladene Paket muss lediglich ausgepackt werden. Ändern Sie dazu die Dateiendung auf „.zip“, dann lässt sich die Datei direkt mit Windows entpacken. Die Bibliothek finden Sie im Pfad „lib\net462“.

Zur Einbindung in PowerShell wird nur eine Zeile Code benötigt:

Add-Type -Path '<Hier Pfad einfügen>\Oracle.ManagedDataAccess.dll'

Damit stehen innerhalb dieser PowerShell-Sitzung nun alle Klassen zur Verfügung, die wir zum Zugriff auf die Oracle-Datenbank benötigen. Falls Sie die aktuelle Version aus dem NuGet-Paket nutzen, werden Sie allerdings eine Fehlermeldung sehen. Diese kann ignoriert werden, da die notwendigen Teile der Bibliothek erfolgreich geladen werden konnten. Falls Sie die Meldung unterdrücken möchten, nutzen Sie stattdessen diese Zeile:

try { Add-Type -Path '<Hier Pfad einfügen>\Oracle.ManagedDataAccess.dll' } catch { }

Um den Code für die tägliche Arbeit übersichtlich zu gestalten, empfehle ich den Einsatz von zwei eigenen Befehlen als Wrapper, um die eigentlichen Aufrufe der .NET-Klassen: „Connect-OraInstance“ und „Invoke-OraQuery“. Sie können zunächst mit meiner Implementierung starten und dann selbst bei Bedarf Erweiterungen vornehmen. Laden Sie sich einfach die beiden Dateien „Connect-OraInstance.ps1“ und „Invoke-OraQuery.ps1“ aus meinem Repository auf GitHub herunter. Dort finden Sie auch weitere Informationen zu diesem Thema und weitere Beispiele.

Der Anwendungsfall

Bei meinem Kunden läuft eine Applikation in verschiedenen Testumgebungen, deren Oracle-Datenbanken sich gegenseitig „nicht sehen“, zwischen denen ich also keinen Datenbank-Link einrichten kann. Trotzdem möchte der Kunde Abweichungen in der von der Applikation genutzten Konfigurationstabelle zwischen den Umgebungen darstellen. Zum Glück habe ich einen zentralen Rechner, von dem aus ich alle Datenbanken erreichen kann.

Der Vorteil von PowerShell gegenüber zum Beispiel sql*plus liegt hier im Format der empfangenen Daten. Mit PowerShell bekomme ich strukturierte Daten, also in einer Struktur von Zeilen und Spalten, mit den korrekten Datentypen. Zahlen sind weiterhin Zahlen und Datumswerte sind weiterhin Datumswerte. Mit vielen anderen Tools, so auch mit sql*plus, bekomme ich lediglich Text, den ich dann wieder aufbereiten muss.  

Ein paar Beispieldaten 

Damit Sie das Ganze auch bei sich direkt nachvollziehen können, hier die Struktur der Tabelle und ein paar Beispieldaten: 

CREATE TABLE config (key VARCHAR2(50), value VARCHAR2(50), CONSTRAINT config_pk PRIMARY KEY (key)); 
INSERT INTO config VALUES ('key1', 'Sample'); 
INSERT INTO config VALUES ('key2', '0815'); 
INSERT INTO config VALUES ('key3', 'true'); 
INSERT INTO config VALUES ('key4', 'false'); 
COMMIT;  

Damit sich die Umgebungen unterscheiden und mein Skript etwas zu zeigen hat, führen Sie auf einer der Umgebungen noch eine Änderung aus:

UPDATE config SET value = 'true' WHERE key = 'key4';

COMMIT;

Die Verbindungen herstellen 

Hier kommen die ersten Zeilen PowerShell-Code, die zunächst einmal die Bibliothek laden, die zwei Wrapper-Befehle erstellen und dann die beiden Verbindungen herstellen. Dazu müssen Sie die Instanzen im Code entsprechend anpassen, natürlich können Sie dabei TNS-Aliase verwenden. Die Benutzer und deren Kennwörter werden interaktiv abgefragt, es soll ja kein Kennwort im Code stehen. 

Add-Type -Path '<Hier Pfad einfügen>\Oracle.ManagedDataAccess.dll' 
. <Hier Pfad einfügen>\Connect-OraInstance.ps1 
. <Hier Pfad einfügen>\Invoke-OraQuery.ps1 
$instance1 = '<Hier die Verbindung zur Instanz 1 konfigurieren>' 
$instance2 = '<Hier die Verbindung zur Instanz 2 konfigurieren>' 
$credential1 = Get-Credential -Message 'Bitte Benutzer und Kennwort für die Instanz 1 eintragen' 
$credential2 = Get-Credential -Message 'Bitte Benutzer und Kennwort für die Instanz 2 eintragen' 
$connection1 = Connect-OraInstance -Instance $instance1 -Credential $credential1 
$connection2 = Connect-OraInstance -Instance $instance2 -Credential $credential2  

Die Daten abfragen und vergleichen 

Zunächst werden über beide Verbindungen die Daten abgefragt und in Variablen gespeichert. Durch die Speicherung in Variablen kann ich in dieser PowerShell-Sitzung auch weiter auf die Daten zugreifen und diese auf verschiedene Arten und Weisen verarbeiten oder auch in verschiedenen Formaten speichern.

In einem ersten Verarbeitungsschritt ermittle ich alle Schlüssel, denn es könnte ja ein bestimmter Schlüssel nur auf einer Umgebung verwendet werden. In der Variablen $keys habe ich eine Liste der Schlüssel ohne Duplikate, die ich nun in einer foreach-Schleife durchlaufen kann. Darin ermittle ich zunächst die Werte zum aktuellen Schlüssel für die beiden hier betrachteten Umgebungen. Die Syntax mit „Where“ erinnert zwar an SQL, aber die Datenbank wird hier nicht mehr befragt. Der Zugriff auf eine bestimmte Spalte meines Ergebnisses erfolgt hier über die Syntax „.“.

Schon die Daten in $data1 und $data2 liegen als Array von PowerShell-Objekten vor und auch das Ergebnis meiner Verarbeitung soll wieder ein Array von PowerShell-Objekten sein. Denn damit lässt sich innerhalb von PowerShell am besten arbeiten. Daher erzeuge ich für jeden Schlüssel ein neues Objekt mit den beiden Werten aus den beiden Umgebungen. Als weitere Eigenschaft (also wie eine weitere Spalte in der Datenbankwelt) füge ich dann auch gleich die Information hinzu, ob die Werte abweichen. Bei zwei Umgebungen ist das nicht zwingend notwendig, aber wenn Sie auf die gleiche Weise fünf oder mehr Umgebungen abfragen, dann hilft es schon.

Abschließend wird die Liste der Vergleichsobjekte in Form einer Tabelle auf dem Bildschirm ausgegeben. 

$query = "SELECT * FROM config" 
$data1 = Invoke-OraQuery -Connection $connection1 -Query $query 
$data2 = Invoke-OraQuery -Connection $connection2 -Query $query 
$keys = $data1.key + $data2.key | Select-Object -Unique 
$comparison = foreach ($key in $keys) { 
    $value1 = ($data1 | Where-Object KEY -eq $key).VALUE 
    $value2 = ($data2 | Where-Object KEY -eq $key).VALUE 
    [PSCustomObject]@{ 
        Key    = $key 
        Value1 = $value1 
        Value2 = $value2 
        Diff
    } 
} 
$comparison | Format-Table 

Die Ausgabe kann noch weiter eingeschränkt werden, zum Beispiel auf die erkannten Abweichungen. Dabei ist auch eine Sortierung möglich, um bei größeren Datenmengen eine gute Übersicht zu haben.

Zudem könnten diese Daten auch gespeichert werden, zum Beispiel auch im beliebten JSON-Format. Sehr gerne nutze ich auch das PowerShell Modul „ImportExcel“ von Doug Finke, um mit sehr wenigen Zeilen Code ansprechende Excel-Tabellen zu erzeugen. Weitere Code-Beispiele dazu finden Sie hier.

Wenn Ihnen jetzt auch in Ihrer Umgebung ein paar Tabellen einfallen, die schon immer mal übersichtlich vergleichen wollten, dann sprechen Sie uns an. Wir helfen gerne. 

Seminarempfehlung

Principal Consultant bei ORDIX

 

Kommentare

Derzeit gibt es keine Kommentare. Schreibe den ersten Kommentar!
Donnerstag, 28. März 2024

Sicherheitscode (Captcha)

×
Informiert bleiben!

Bei Updates im Blog, informieren wir per E-Mail.

Weitere Artikel in der Kategorie