📚 Qlik Sense Kurs – Artikel 20 von 28
← Vorheriger Artikel: Data Quality Gates
→ Nächster Artikel: Monitoring & Logging
Was ist Error Handling? Die systematische Behandlung von Fehlern im Script – Fehler erkennen, loggen und automatisch wiederherstellen, statt das Script einfach abbrechen zu lassen. Dies ist ein entscheidender Schritt von der Entwicklung zur produktiven BI-Anwendung.
Was kannst Du über Error Handling & Recovery im Script lernen?
Nach diesem Guide kannst Du:
- ErrorMode und Error Variables strategisch einsetzen, um Fehler kontrolliert abzufangen.
- Umfassende Error Logging Frameworks implementieren, um Fehler historisch nachzuverfolgen.
- Robuste Recovery-Strategien (Fallback-Mechanismen) für kritische Load-Vorgänge nutzen.
- Proaktive Prüfmechanismen implementieren, um Fehler zu verhindern, bevor sie auftreten.
Zeitinvestment: 30 Min Lesen + 4 Std Hands-on
Quick Win: In 15 Minuten hast Du erste Error Checks implementiert
Warum sind Fehler im Script erwartbar?
Das Problem: Eine Quelldatei fehlt (Error Code 8), die Datenbankverbindung bricht ab (Error Code 9) oder ein Datenformat ist korrupt – und das Script bricht ohne Recovery-Strategie ab. Keine Daten = keine Analysen!
Die Lösung: Antizipiere Fehler, fange sie mit `SET ErrorMode = 0` ab, logge sie mit Systemvariablen (`ScriptError`), und stelle automatisch auf Backup-Daten um!
Was sind die 4 Säulen des Error Handlings?
| Säule | Funktion | Tools |
|---|---|---|
| 1. ErrorMode | Steuert das globale Script-Verhalten bei Fehler | SET ErrorMode = 0/1 |
| 2. Error Variables | Fängt detaillierte Fehler-Informationen ab | ScriptError, ScriptErrorDetails |
| 3. Error Logging | Protokollierung für Monitoring und historische Analyse | QVD/TXT Logs |
| 4. Recovery | Automatische Wiederherstellung von Daten | Backup QVDs, Fallback-Strategien |
Was ist ErrorMode – das Fundament der Steuerung?
Die Anweisung `SET ErrorMode` ist das wichtigste Werkzeug, um das Skript kontrolliert zu steuern.
Wie funktioniert ErrorMode = 1 (Standard: Stop on Error) im Script?
// Standard: Script stoppt bei Fehler
LOAD * FROM (ooxml, embedded labels);
// Bei Fehler: Script bricht ab, keine weitere Verarbeitung
Wann verwenden? Kritische Loads, bei denen fehlerhafte Daten inakzeptabel sind, oder während der Entwicklung. Da Qlik Sense bei jedem Fehler eine Fehlermeldung generiert, ist das Standardverhalten sicher.
Wie funktioniert ErrorMode = 0 (Continue on Error) im Script?
SET ErrorMode = 0; // Fehler nicht abbrechen
LOAD * FROM (ooxml, embedded labels);
// Bei Fehler: Script läuft weiter, Error Variables werden gesetzt
IF ScriptError <> 0 THEN
TRACE Sales.xlsx failed: $(ScriptErrorDetails);
// Recovery Logic hier einfügen
ENDIF
SET ErrorMode = 1; // WICHTIG: Zurücksetzen!
Wann verwenden? Für nicht-kritische oder optionale Datenquellen sowie für Produktions-Loads, bei denen ein Fallback (Backup) implementiert ist. Du musst **sofort** prüfen, ob ein Fehler aufgetreten ist.
Wichtig: ErrorMode = 0 bedeutet NICHT «Fehler ignorieren»! Du MUSST den `ScriptError` prüfen und behandeln, da sonst das Skript mit potenziell fehlenden Daten durchläuft!
Wie erfasse ich Fehler-Informationen mit Error Variables?
Qlik Sense liefert nach jeder Operation Systemvariablen mit detaillierten Fehlerinformationen.
| Variable | Inhalt | Beispiel |
|---|---|---|
| ScriptError | Error Code (0 = kein Fehler) | 8 (File not found) |
| ScriptErrorDetails | Detaillierte Fehlermeldung als Text | «File ‚Sales.xlsx‘ not found» |
| ScriptErrorList | Liste aller seit dem letzten Reset aufgetretenen Fehler | «Error 8:…nError 16:…» |
Goldene Regel: Error Variablen sofort speichern!
Error Variablen werden nach JEDEM erfolgreichen Skript-Statement auf 0 zurückgesetzt. Wenn das nächste Statement erfolgreich ist, überschreibt es den Fehlerstatus des vorherigen Statements. Speichere sie daher sofort nach der fehlerhaften Operation in einer eigenen Variablen.
SET ErrorMode = 0;
// Operation mit Fehler
LOAD * FROM (ooxml, embedded labels);
LET vError1 = ScriptError; // Fehler wird SOFORT in vError1 gesichert!
LET vErrorDetail1 = ScriptErrorDetails;
// Nächstes Statement (erfolgreich)
LOAD * FROM (ooxml, embedded labels);
// ScriptError ist jetzt 0, egal ob File1 fehlschlug.
Wie funktioniert das Basic Error Handling Pattern & Recovery?
Dies ist das Standard-Pattern, das Du für jeden kritischen Load-Vorgang verwenden solltest.
SET ErrorMode = 0; // Continue on error
// Kritische Operation
LOAD
OrderID,
CustomerID,
Amount
FROM
(ooxml, embedded labels);
// Check auf Fehler
IF ScriptError <> 0 THEN
TRACE Failed to load Sales.xlsx;
TRACE Details: $(ScriptErrorDetails);
TRACE Code: $(ScriptError);
// Recovery: Fallback zu Backup-QVD
LOAD * FROM (qvd);
TRACE Loaded backup data;
ELSE
TRACE Sales.xlsx loaded successfully;
ENDIF
SET ErrorMode = 1; // Restore default
Erklärung: Die Wiederherstellung (Recovery) erfolgt, indem man bei einem Fehlercode unbesehen die Backup-Daten aus einem QVD lädt. Bei einem fehlerfreien Load springt die IF-Bedingung über den Recovery-Block hinweg.
Was ist das Error Logging Framework im Script für Error Handling & Recovery?
Ein strukturiertes Logging-Framework ermöglicht die Überwachung aller Fehler über die Zeit. Die Daten werden in einer zentralen Tabelle gesammelt und in einem QVD gespeichert, das Sie in einem separaten Quality-Dashboard analysieren können (siehe Data Quality Gates).
//===============================================
// Error Logging Framework
//===============================================
// 1. Log laden (oder initialisieren, falls nicht existiert)
IF NOT FileSize('[LogsErrorLog.qvd]') > 0 THEN
Error_Log:
LOAD
Timestamp#(Null()) as ErrorTime,
Text(Null()) as ScriptSection,
Num(Null()) as ErrorCode,
Text(Null()) as ErrorMessage
AUTOGENERATE 0;
ENDIF
// 2. Load existing log (falls vorhanden)
Error_Log:
LOAD * FROM [LogsErrorLog.qvd] (qvd);
// 3. SUB für wiederverwendbares Logging definieren
SUB LogError(vSection, vErrorCode, vErrorMsg, vRecovery)
CONCATENATE(Error_Log)
LOAD
Now() as ErrorTime,
'$(vSection)' as ScriptSection,
$(vErrorCode) as ErrorCode,
'$(vErrorMsg)' as ErrorMessage,
'$(vRecovery)' as RecoveryAction
AUTOGENERATE 1;
TRACE $(vSection) | Code: $(vErrorCode) | $(vErrorMsg);
END SUB
Verwendung:
SET ErrorMode = 0;
LOAD * FROM (ooxml, embedded labels);
IF ScriptError <> 0 THEN
CALL LogError('Data Load', $(ScriptError), '$(ScriptErrorDetails)', 'Loaded from backup');
// Recovery
LOAD * FROM (qvd);
ENDIF
// Error Log am Ende speichern
STORE Error_Log INTO [LogsErrorLog.qvd] (qvd);
SET ErrorMode = 1;
Wie kann man Proactive Error Prevention im Script vorher prüfen?
Die eleganteste Form des Error Handlings ist die Prävention: Prüfe, ob eine Datei überhaupt existiert, bevor Du versuchst, sie zu laden. Dies nutzt die Qlik-Funktion `FileSize()`.
// SUB: Prüft ob Datei existiert und größer als 0 Bytes ist
SUB CheckFileExists(vFilePath, vFileExistsVariable)
LET vFileSize = FileSize('$(vFilePath)');
IF IsNum(vFileSize) AND $(vFileSize) > 0 THEN
LET $(vFileExistsVariable) = 1; // Variable auf 1 setzen
TRACE [CHECK] File exists: $(vFilePath);
ELSE
LET $(vFileExistsVariable) = 0; // Variable auf 0 setzen
TRACE [CHECK] File NOT found: $(vFilePath);
ENDIF
END SUB
// Anwendung: Prüfe, ob Sales.xlsx existiert
CALL CheckFileExists('', vSalesFileExists);
IF $(vSalesFileExists) = 1 THEN
// File exists, proceed with load
LOAD * FROM (ooxml, embedded labels);
ELSE
// File missing, Recovery-Pfad einleiten
TRACE Sales.xlsx not found, trying backup;
CALL CheckFileExists('', vBackupExists);
IF $(vBackupExists) = 1 THEN
LOAD * FROM (qvd);
ELSE
TRACE No data available! Aborting.;
EXIT SCRIPT;
ENDIF
ENDIF
Erklärung:
- FileSize(): Gibt die Größe der Datei in Bytes zurück (NULL oder -1, wenn sie nicht existiert).
- IsNum(): Stellt sicher, dass `FileSize` einen gültigen numerischen Wert zurückgegeben hat.
- Cascade: Wir prüfen in einer Kaskade: Originalquelle → Backup-Quelle → Abbruch (`EXIT SCRIPT`).
Wie behandelt man Database Connection Error im Script?
Fehler bei Datenbank-Verbindungen sind besonders häufig. Hier kann ein Test-Query vor dem eigentlichen Daten-Load helfen.
SET ErrorMode = 0;
// Teste die Datenbankverbindung
LIB CONNECT TO 'DatabaseConnection';
// Test Query: Wähle 1 Record aus
Test_Connection:
LOAD 1 as TestField;
SQL SELECT 1 as TestField FROM DUAL;
IF ScriptError <> 0 THEN
TRACE Database connection failed! Code: $(ScriptError);
// Recovery: Nutze gecachte QVD-Daten
Sales:
LOAD * FROM (qvd);
TRACE Using cached data from QVD;
SET vDataFreshness = 'Cached';
ELSE
// Connection OK, lade neue Daten
DROP TABLE Test_Connection;
//... (Load Fresh Data Logic)...
// Nach erfolgreichem Load: QVD cachen
STORE Sales INTO (qvd);
TRACE Fresh data loaded and cached;
SET vDataFreshness = 'Fresh';
ENDIF
SET ErrorMode = 1;
Recovery-Strategie: Bei einem Connection-Fehler wird sofort auf den Cache (letztes funktionierendes QVD) umgestellt. Bei einem erfolgreichen Load wird der Cache aktualisiert und die neue Daten-Qualität (`vDataFreshness = ‚Fresh’`) ist gesichert. Dieses Pattern ist ideal für Incremental Loads.
Was ist die Rollback-Strategie für Atomic Loads?
Ein Rollback stellt sicher, dass, wenn der neue Load fehlschlägt oder die Daten korrupt sind (siehe Data Quality Checks), die letzte bekannte «gute» Version der Daten beibehalten wird. Das Konzept des *Atomic Load* bedeutet: Entweder alles oder nichts.
Wir erweitern das Backup-Pattern:
// Step 1: Backup current QVD
IF FileSize('') > 0 THEN
// Kopiere die aktuelle QVD auf eine Backup-Datei
EXECUTE cmd.exe /C copy "" "";
TRACE Current QVD backed up;
ENDIF
// Step 2: Load new data (in temporäre Tabelle)
SET ErrorMode = 0;
Temp_Sales:
LOAD *
FROM (ooxml, embedded labels);
// Step 3: Validierung der neuen Daten
LET vNewRowCount = NoOfRows('Temp_Sales');
LET vNullCount = Sum(If(IsNull(OrderID), 1, 0), 'Temp_Sales');
TRACE New data: $(vNewRowCount) rows, $(vNullCount) nulls;
// Step 4: Decision - Accept or Rollback
IF ScriptError <> 0 THEN
TRACE Load failed, rolling back;
ELSEIF $(vNewRowCount) = 0 THEN
TRACE No data loaded, rolling back;
ELSEIF $(vNullCount) > $(vNewRowCount) * 0.1 THEN // Über 10% NULLs = Quality Check
TRACE Too many NULLs (>10%), rolling back;
ELSE
// AKZEPTIERE NEUE DATEN: Lade Temp_Sales ins finale QVD
Sales:
LOAD * RESIDENT Temp_Sales;
DROP TABLE Temp_Sales;
// Speichere als neuen "guten" Zustand
STORE Sales INTO (qvd);
TRACE New data accepted and stored;
ENDIF
SET ErrorMode = 1;
Erklärung der Rollback-Bedingungen: Ein Rollback wird nicht nur bei technischen Fehlern (`ScriptError`), sondern auch bei kritischen Quality Issues (z.B. zu viele `NULL` Values) ausgelöst. In all diesen Fehlerfällen wird die `Sales`-Tabelle mit dem Backup-QVD (`Sales_LastGood.qvd`) befüllt.
Was sind die Best Practices für Error Handling & Recovery im Script?
Halten Sie sich an diese Regeln, um einen robusten und wartbaren Load-Script zu gewährleisten:
✓ ErrorMode Management:
- [ ] Default belassen (`ErrorMode = 1`) – nur für spezifische Blöcke auf 0 setzen.
- [ ] Immer auf 1 zurücksetzen, wenn der Fehler-Handling-Block beendet ist.
✓ Error Variables:
- [ ] SOFORT nach der Operation in eigene Variable speichern.
- [ ]
ScriptErrorUNDScriptErrorDetailsfür das Logging erfassen.
✓ Recovery Strategy:
- [ ] Proactive Error Prevention (
FileSizeCheck) implementieren. - [ ] Fallback zu Backup QVDs als primäre Strategie nutzen.
- [ ] `EXIT SCRIPT` nur bei kritischen, nicht behebbaren Fehlern verwenden.
Wie behebe ich Fehler und finde Lösungen im Script?
⚠️ Problem: ScriptError ist immer 0, obwohl Fehler auftreten
Ursache: ErrorMode = 0, aber Du prüfst `ScriptError` zu spät (nach dem nächsten erfolgreichen Statement).
Lösung: Sofort nach Operation prüfen und speichern:
SET ErrorMode = 0;
LOAD * FROM NonExistentFile.xlsx;
LET vError = ScriptError; // SOFORT!
TRACE ScriptError: $(vError);
⚠️ Problem: Datenbankverbindung schlägt fehl (Code 3 oder 9)
Ursache: Datenbank offline (Code 9: Database not found) oder Timeout/Login-Fehler (Code 3: General ODBC error).
Lösung: Test-Query-Pattern (siehe oben) mit Fallback zu QVD-Cache. Bei Datenbank-Fehlern ist es oft besser, auf ältere Cached-Daten zurückzugreifen, als den gesamten Load abzubrechen.
⚠️ Problem: Zu viele Error Logs, Logs werden zu groß
Lösung: Log-Rotation implementieren
Begrenze die Log-Tabelle auf eine feste Anzahl von Records (z.B. die letzten 1.000 Einträge), bevor sie als QVD gespeichert wird:
// Nur die letzten 1000 Records behalten
Error_Log:
LOAD * FROM [LogsErrorLog.qvd] (qvd)
ORDER BY ErrorTime DESC;
FIRST 1000 LOAD * RESIDENT Error_Log;
DROP TABLE Error_Log;
STORE Error_Log INTO [LogsErrorLog.qvd] (qvd);
Was sind die nächsten Schritte bei Error Handling & Recovery im Script?
Du kannst jetzt robuste Error Handling Strategien implementieren! Als nächstes:
1. Monitoring & Logging: Der nächste Artikel (Monitoring & Logging) zeigt Dir, wie Du diese historischen Error Logs in Dashboards visualisierst, um Trends in der Datenqualität zu erkennen.
2. Incremental Loading: Erfahre, wie Error Recovery bei Delta Loads funktioniert. Im Artikel zu Incremental Loading wird erklärt, wie du bei einem fehlerhaften Delta-Load automatisch auf einen Full Load zurückfällst.
Welche verwandten Themen gibt es im Kurs zu Error Handling & Recovery im Script?
- Data Quality Gates – Wie man Fehler frühzeitig im Script erkennt (der vorherige Artikel).
- Incremental Loading – Error Recovery bei Delta Loads.