SAP-B1-Abfragen von SQL Server nach HANA migrieren
Von Zain Abbas, Kodenova · Aktualisiert am
Warum Ihre Abfragen auf HANA nicht mehr laufen
Wenn ein Unternehmen SAP Business One von Microsoft SQL Server auf SAP HANA umstellt, werden die Daten sauber übernommen. Das eigene SQL nicht. Gespeicherte Abfragen, Alarme, formatierte Suchen, Commands in Crystal Reports, das SQL von Add-ons und die Transaction Notification enthalten durchweg T-SQL. Und HANA versteht kein T-SQL.
Die meisten Änderungen sind klein. Das Problem ist ihre Menge, und ein einziges vergessenes Anführungszeichen legt die ganze Abfrage lahm. In diesem Leitfaden stehen die Änderungen, die ich am häufigsten vornehme, in der Reihenfolge, in der ich sie prüfe.
1. Jeden Spaltennamen in Anführungszeichen setzen
An dieser Stelle stolpert jeder als Erstes. HANA wandelt Namen ohne Anführungszeichen in Großbuchstaben um. Die Spaltennamen in SAP Business One sind jedoch in gemischter Schreibweise angelegt: CardCode, DocTotal, U_MyField. Aus T0.CardCode wird also T0.CARDCODE, und HANA findet die Spalte nicht.
Die Lösung sind doppelte Anführungszeichen um den Namen:
SELECT T0."DocNum", T0."CardCode", T0."DocTotal"
FROM "OINV" T0
WHERE T0."CANCELED" = 'N'
Daraus ergeben sich zwei Regeln:
- Doppelte Anführungszeichen kennzeichnen einen Bezeichner. Einfache Anführungszeichen kennzeichnen eine Zeichenkette. Auf SQL Server kam man mit
"N"manchmal noch durch. Auf HANA ist"N"eine Spalte namens N, und die Abfrage schlägt fehl. - Auch Aliasnamen gehören in Anführungszeichen, wenn die Schreibweise erhalten bleiben soll:
AS "Customer Name".
2. Die gängigen Funktionen ersetzen
Die folgenden T-SQL-Funktionen finde ich in nahezu jeder SAP-B1-Datenbank, daneben ihre Entsprechungen in HANA.
| SQL Server (T-SQL) | SAP HANA | Hinweis |
|---|---|---|
ISNULL(T0.Comments, '') | IFNULL(T0."Comments", '') | COALESCE funktioniert auf beiden |
GETDATE() | CURRENT_TIMESTAMP | CURRENT_DATE für das reine Datum |
DATEADD(day, 30, T0.DocDate) | ADD_DAYS(T0."DocDate", 30) | Außerdem ADD_MONTHS, ADD_YEARS |
DATEDIFF(day, T0.DocDueDate, GETDATE()) | DAYS_BETWEEN(T0."DocDueDate", CURRENT_DATE) | Gleiche Argumentreihenfolge: von, bis |
CONVERT(varchar, T0.DocDate, 103) | TO_NVARCHAR(T0."DocDate", 'DD/MM/YYYY') | Formatstring statt Stilnummer |
T0.CardCode + ' - ' + T0.CardName | T0."CardCode" || ' - ' || T0."CardName" | + addiert auf HANA nur Zahlen |
SELECT TOP 10 ... | SELECT TOP 10 ... oder LIMIT 10 | TOP funktioniert auf HANA |
#Temp / SELECT INTO | Tabellenvariable oder CREATE LOCAL TEMPORARY TABLE | Erfordert SQLScript |
SELECT GETDATE() | SELECT CURRENT_TIMESTAMP FROM DUMMY | HANA verlangt eine FROM-Klausel |
RIGHT(REPLICATE('0', 8) + T0.CardCode, 8) | LPAD(T0."CardCode", 8, '0') | Auffüllen mit Nullen; RPAD füllt rechts auf. Ein alleinstehendes REPLICATE('-', 10) wird zu LPAD('', 10, '-') |
Ein vollständiges Vorher-nachher-Beispiel anhand einer typischen Abfrage für überfällige Ausgangsrechnungen:
-- SQL Server
SELECT TOP 50
T0.DocNum,
T0.CardCode + ' - ' + T0.CardName AS Customer,
CONVERT(varchar, T0.DocDueDate, 103) AS DueDate,
DATEDIFF(day, T0.DocDueDate, GETDATE()) AS DaysLate,
ISNULL(T0.Comments, '') AS Comments
FROM OINV T0
WHERE T0.DocStatus = 'O'
AND T0.DocDueDate < DATEADD(day, -30, GETDATE())
ORDER BY DaysLate DESC
-- SAP HANA
SELECT TOP 50
T0."DocNum",
T0."CardCode" || ' - ' || T0."CardName" AS "Customer",
TO_NVARCHAR(T0."DocDueDate", 'DD/MM/YYYY') AS "DueDate",
DAYS_BETWEEN(T0."DocDueDate", CURRENT_DATE) AS "DaysLate",
IFNULL(T0."Comments", '') AS "Comments"
FROM "OINV" T0
WHERE T0."DocStatus" = 'O'
AND T0."DocDueDate" < ADD_DAYS(CURRENT_DATE, -30)
ORDER BY "DaysLate" DESC
Sie können Ihr eigenes T-SQL in unseren kostenlosen SQL-to-HANA-Converter einfügen und erhalten einen ersten Entwurf dieser Änderungen.
3. Die B1-Parameter unverändert lassen
Gespeicherte Abfragen, die beim Benutzer Werte abfragen, arbeiten mit [%0], [%1] und so weiter. SAP Business One ersetzt diese Platzhalter, bevor das SQL die Datenbank erreicht. Auf HANA bleiben sie deshalb gleich:
SELECT T0."DocNum", T0."DocDate", T0."DocTotal"
FROM "ORDR" T0
WHERE T0."DocDate" >= [%0]
AND T0."DocDate" <= [%1]
Formatierte Suchen funktionieren genauso. Verweise wie $[$38.1.0] oder $[ORDR."CardCode"] füllt der Client aus. Umstellen müssen Sie nur das SQL drumherum. Achten Sie auf die Anführungszeichen innerhalb des Feldverweises: Für Tabelle und Spalte gelten dieselben HANA-Regeln.
4. Stored Procedures und temporäre Tabellen brauchen SQLScript
Hier hilft Suchen und Ersetzen nicht mehr weiter. T-SQL-Prozeduren verwenden @variables, #temp-Tabellen, SELECT INTO, WHILE-Schleifen und Cursor. HANA-Prozeduren werden in SQLScript geschrieben, und das ist anders aufgebaut:
- Variablen werden mit
DECLAREdeklariert und mit vorangestelltem Doppelpunkt gelesen::lv_total. - Zwischenergebnisse landen in der Regel in Tabellenvariablen (
lt_open = SELECT ...;), nicht in temporären Tabellen. - HANA kennt zwar lokale temporäre Tabellen (ebenfalls mit
#benannt), diese müssen Sie aber zuerst mit expliziten Spalten anlegen. EinSELECT INTO #tempgibt es nicht. - Jede Anweisung endet mit einem Semikolon.
-- SQLScript: open order value per customer
CREATE PROCEDURE "KN_OPEN_ORDERS" (IN p_from DATE)
LANGUAGE SQLSCRIPT AS
BEGIN
lt_orders = SELECT "CardCode", "DocTotal"
FROM "ORDR"
WHERE "DocStatus" = 'O' AND "DocDate" >= :p_from;
SELECT "CardCode", SUM("DocTotal") AS "OpenValue"
FROM :lt_orders
GROUP BY "CardCode";
END;
T-SQL-Skripte, die Sie von Hand ausführen und die mit DECLARE @x beginnen, haben außerhalb einer Prozedur keine direkte Entsprechung in HANA. Verpacken Sie sie in einen anonymen Block, DO BEGIN ... END;. Er führt SQLScript einmalig aus, ohne eine Prozedur anzulegen:
-- T-SQL
DECLARE @from DATE = '2026-01-01';
SELECT CardCode, SUM(DocTotal) FROM ORDR WHERE DocDate >= @from GROUP BY CardCode;
-- SQLScript anonymous block
DO BEGIN
DECLARE lv_from DATE := '2026-01-01';
SELECT "CardCode", SUM("DocTotal") AS "Total"
FROM "ORDR"
WHERE "DocDate" >= :lv_from
GROUP BY "CardCode";
END;
Anonyme Blöcke unterstützen dieselben Anweisungen wie ein Prozedurrumpf, lassen sich aber nicht innerhalb einer Prozedur oder Funktion verwenden.
Prozeduren, die stark auf Cursorn aufbauen, lohnt es sich bei dieser Gelegenheit als mengenbasierte Abfragen neu zu entwerfen. HANA dankt es Ihnen.
5. SBO_SP_TransactionNotification
Auf HANA liefert SAP Business One die Transaction Notification als SQLScript-Prozedur aus. Sie erhält dieselben Eingaben wie bisher (Objekttyp, Transaktionstyp, Schlüsselspalten und deren Werte) und gibt Fehlercode und Fehlermeldung am Ende mit einem SELECT ... FROM DUMMY zurück. Die vollständigen Regeln im direkten Vergleich finden Sie in diesen TransactionNotification-Beispielen für SQL Server und HANA.
Ihre Prüfblöcke aus T-SQL müssen innerhalb dieser Prozedur neu geschrieben werden. Ein typischer Block sieht so aus:
IF :object_type = '17' AND (:transaction_type = 'A' OR :transaction_type = 'U') THEN
SELECT COUNT(*) INTO cnt
FROM "ORDR"
WHERE "DocEntry" = :list_of_cols_val_tab_del
AND IFNULL("NumAtCard", '') = '';
IF :cnt > 0 THEN
error := 1;
error_message := 'Customer reference is required';
END IF;
END IF;
Deklarieren Sie cnt am Anfang der Prozedur. Halten Sie jede Regel klein und testen Sie Hinzufügen und Aktualisieren getrennt. Ein einziger Syntaxfehler an dieser Stelle blockiert sämtliche Belege im Mandanten. Spielen Sie die Prozedur deshalb außerhalb der Arbeitszeiten ein.
6. Commands in Crystal Reports
Crystal Reports, die auf SQL Server erstellt wurden, verwenden häufig einen Command (eine eingefügte SQL-Anweisung) oder rufen eine Stored Procedure auf. Beides enthält T-SQL. Für jeden Bericht gilt:
- Das SQL des Commands bzw. die Prozedur in HANA-Syntax umwandeln.
- Den Bericht über Database > Set Datasource Location auf die HANA-Datenquelle umstellen, mit HANA-Verbindung, Anmeldedaten und dem Schema des Mandanten.
- Prüfen, ob die Parameterfelder weiterhin den Parametern des Commands zugeordnet sind.
- Den Bericht im SAP-Business-One-Client für HANA in der Vorschau öffnen und die Ausgabe mit der SQL-Server-Version vergleichen.
Berichte, die direkt auf Tabellen ohne Commands aufbauen, brauchen meist nur Schritt 2.
7. Ein Testvorgehen, das Fehler aufdeckt
Eine umgewandelte Abfrage, die läuft, ist noch lange keine umgewandelte Abfrage, die stimmt. Die Verkettung von Zeichenketten mit + ist die klassische Falle: Auf HANA schlägt sie entweder fehl oder versucht, die Werte als Zahlen zu addieren. Datumsformate sind eine weitere.
- Zuerst eine Bestandsaufnahme. Exportieren Sie die Liste der gespeicherten Abfragen (OUQR), formatierten Suchen (CSHS), Alarme, Crystal Reports, benutzerdefinierten Prozeduren und die Transaction Notification. Notieren Sie, wer was nutzt. Vieles wird gar nicht mehr verwendet und kann entfallen.
- In Paketen nach Typ umstellen: einfache Abfragen, formatierte Suchen, Berichte, dann Prozeduren.
- Beide Versionen ausführen, SQL Server und HANA, jeweils auf einer Kopie desselben Datenbestands.
- Zeilenanzahl und Summen vergleichen. Wenn sich die Summen von DocTotal oder die Anzahlen unterscheiden, klären Sie die Ursache, bevor Sie weitermachen.
- Grenzfälle testen. NULL-Werte, stornierte Belege, Fremdwährung und Belege über einen Jahreswechsel hinweg.
- Abnahme durch die Key-User: Lassen Sie die Berichte, mit denen sie täglich arbeiten, von ihnen freigeben.
Als Ausgangspunkt enthält unsere SAP-B1-Abfragebibliothek gängige Abfragen in T-SQL- und HANA-Syntax, und der SQL-to-HANA-Converter beschleunigt den ersten Durchgang für Ihre eigenen Abfragen.
Womit Sie rechnen sollten
Einfache gespeicherte Abfragen dauern jeweils wenige Minuten. Formatierte Suchen ähnlich. Berichte mit Commands dauern wegen der Tests länger. Stored Procedures und die Transaction Notification kosten die meiste Zeit und bergen das größte Risiko. Nehmen Sie sie deshalb als Erstes in Angriff, nicht als Letztes.
Wenn Sie eine Umstellung auf HANA planen und Ihre Abfragen, Berichte und Prüfregeln umgewandelt und getestet haben möchten, kontaktieren Sie Kodenova mit einer Liste dessen, was bei Ihnen im Einsatz ist.
Quellen
- SAP (B1SA): Query Migration Tool für Microsoft SQL Server nach SAP HANA (GitHub)
- SAP HANA SQL Reference: Funktion IFNULL
- SAP HANA SQL Reference: Funktion LPAD (String)
- SAP HANA SQLScript Reference: Anonymer Block (Anonymous Block)
- SAP HANA SQL Reference: Funktion DAYS_BETWEEN
- SAP HANA SQL Reference: Datums- und Zeitfunktionen (Datetime Functions)
- SAP Community: Crystal Report für SAP B1 von MS SQL nach HANA umstellen
- SAP Community: SBO-HANA-Abfrage mit Benutzerparametern
Passende Leistungen
Häufige Fragen
Funktionieren SAP-Business-One-Abfragen auf HANA ohne Änderungen?
Nur die einfachsten. Jede Abfrage, die Spaltennamen in gemischter Schreibweise ohne Anführungszeichen, ISNULL, GETDATE, DATEADD, CONVERT oder + für Zeichenketten verwendet, schlägt auf HANA fehl oder liefert falsche Ergebnisse. Abfragen aus dem Abfragegenerator brauchen meist weniger Anpassungen.
Warum meldet HANA einen ungültigen Spaltennamen, obwohl die Spalte existiert?
HANA wandelt Bezeichner ohne Anführungszeichen in Großbuchstaben um. Die Spalten in SAP Business One sind in gemischter Schreibweise angelegt, etwa CardCode. Sie müssen also T0."CardCode" mit doppelten Anführungszeichen schreiben. Tabellennamen wie OINV sind bereits großgeschrieben, aber auch sie in Anführungszeichen zu setzen, ist eine sichere Gewohnheit.
Funktionieren die Parameter [%0] in gespeicherten Abfragen auch auf HANA?
Ja. Parameter im Stil von [%0] und [%1] verarbeitet SAP Business One selbst, bevor das SQL die Datenbank erreicht. Sie bleiben also unverändert. Anpassen müssen Sie nur das SQL drumherum.
Gibt es ein Tool, das T-SQL automatisch in HANA-SQL umwandelt?
SAP hat auf GitHub ein Query Migration Tool veröffentlicht, das einen großen Teil von T-SQL umwandelt. Das Projekt ist jedoch archiviert, und SAP weist darauf hin, dass Sie das Ergebnis prüfen müssen. Unser kostenloser SQL-to-HANA-Converter deckt die gängigen SAP-B1-Muster ab. In beiden Fällen sollte ein Mensch jede umgewandelte Abfrage testen.
Was ist der schwierigste Teil der Migration?
Stored Procedures, temporäre Tabellen, Cursor und SBO_SP_TransactionNotification. Hier ist eine saubere Neuentwicklung in SQLScript nötig, kein Suchen und Ersetzen.
Bereit für den Start?
Sagen Sie uns, was Sie brauchen. Sie erhalten eine klare technische Antwort, einen festen Leistungsumfang und einen Preis, in der Regel innerhalb von 24 Stunden.
