Moving SAP Business One from SQL Server to HANA: how to convert your queries, reports and formatted searches
By Zain Abbas, Kodenova · Updated
Why your queries break on HANA
When a company moves SAP Business One from Microsoft SQL Server to SAP HANA, the data moves over cleanly. The custom SQL does not. Saved queries, alerts, formatted searches, Crystal Reports commands, add-on SQL and the transaction notification all carry T-SQL. HANA does not speak T-SQL.
Most of the changes are small. The trouble is that there are many of them, and one missed quote stops the whole query. This guide lists the changes we make most often, in the order we check them.
1. Quote every column name
This is the change that catches everyone first. HANA turns unquoted names into upper case. SAP Business One column names are mixed case: CardCode, DocTotal, U_MyField. So T0.CardCode becomes T0.CARDCODE, and HANA cannot find it.
The fix is double quotes around the name:
SELECT T0."DocNum", T0."CardCode", T0."DocTotal"
FROM "OINV" T0
WHERE T0."CANCELED" = 'N'
Two rules follow from this:
- Double quotes mean an identifier. Single quotes mean a string. In SQL Server you could sometimes get away with
"N". On HANA,"N"is a column called N, and the query fails. - Aliases are quoted too if you want to keep their case:
AS "Customer Name".
2. Swap the common functions
These are the T-SQL functions we see in nearly every SAP B1 database, and their HANA equivalents.
| SQL Server (T-SQL) | SAP HANA | Note |
|---|---|---|
ISNULL(T0.Comments, '') | IFNULL(T0."Comments", '') | COALESCE works on both |
GETDATE() | CURRENT_TIMESTAMP | Use CURRENT_DATE for date only |
DATEADD(day, 30, T0.DocDate) | ADD_DAYS(T0."DocDate", 30) | Also ADD_MONTHS, ADD_YEARS |
DATEDIFF(day, T0.DocDueDate, GETDATE()) | DAYS_BETWEEN(T0."DocDueDate", CURRENT_DATE) | Same argument order: from, to |
CONVERT(varchar, T0.DocDate, 103) | TO_NVARCHAR(T0."DocDate", 'DD/MM/YYYY') | Format string replaces style number |
T0.CardCode + ' - ' + T0.CardName | T0."CardCode" || ' - ' || T0."CardName" | + only adds numbers on HANA |
SELECT TOP 10 ... | SELECT TOP 10 ... or LIMIT 10 | TOP works on HANA |
#Temp / SELECT INTO | Table variable or CREATE LOCAL TEMPORARY TABLE | Needs SQLScript |
SELECT GETDATE() | SELECT CURRENT_TIMESTAMP FROM DUMMY | HANA needs a FROM clause |
A full before and after, from a typical overdue invoices query:
-- 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
You can paste your own T-SQL into our free SQL to HANA converter to get a first draft of these changes.
3. Keep the B1 parameters as they are
Saved queries that ask the user for input use [%0], [%1] and so on. SAP Business One replaces these before the SQL reaches the database, so they stay the same on HANA:
SELECT T0."DocNum", T0."DocDate", T0."DocTotal"
FROM "ORDR" T0
WHERE T0."DocDate" >= [%0]
AND T0."DocDate" <= [%1]
Formatted searches work the same way. References like $[$38.1.0] or $[ORDR."CardCode"] are filled in by the client. Only the SQL around them needs converting. Watch the quoting inside the field reference: the table and column follow the same HANA rules.
4. Stored procedures and temp tables need SQLScript
Find-and-replace stops working here. T-SQL procedures use @variables, #temp tables, SELECT INTO, WHILE loops and cursors. HANA procedures are written in SQLScript, which has a different shape:
- Variables are declared with
DECLAREand read with a colon prefix::lv_total. - Intermediate results usually go into table variables (
lt_open = SELECT ...;), not temp tables. - HANA does have local temporary tables (also named with
#), but you must create them with explicit columns first. There is noSELECT INTO #temp. - Each statement ends with a semicolon.
-- 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;
Cursor-heavy procedures are worth redesigning as set-based queries while you are in there. HANA rewards that.
5. SBO_SP_TransactionNotification
On HANA, SAP Business One ships the transaction notification as a SQLScript procedure. It receives the same inputs as before (object type, transaction type, key columns and values) and returns the error code and message at the end with a SELECT ... FROM DUMMY.
Your T-SQL validation blocks must be rewritten inside that procedure. A typical block looks like this:
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;
Declare cnt at the top of the procedure. Keep each rule small and test add and update separately. One syntax error here blocks every document in the company, so deploy it outside working hours.
6. Crystal Reports commands
Crystal Reports built on SQL Server often use a Command (a pasted SQL statement) or call a stored procedure. Both carry T-SQL. For each report:
- Convert the command SQL or the procedure to HANA syntax.
- Point the report at the HANA data source with Database > Set Datasource Location, using the HANA connection, credentials and company schema.
- Check that parameter fields still map to the command parameters.
- Preview it in the SAP Business One HANA client and compare the output with the SQL Server version.
Reports built on plain tables, without commands, usually only need step 2.
7. A testing approach that catches mistakes
A converted query that runs is not the same as a converted query that is right. String concatenation with + is the classic trap: on HANA it may fail, or it may try to add values as numbers. Date formats are another.
- Inventory first. Export the list of saved queries (OUQR), formatted searches (CSHS), alerts, Crystal reports, user procedures and the transaction notification. Note who uses each one. Many will be unused and can be dropped.
- Convert in batches by type: simple queries, formatted searches, reports, then procedures.
- Run both versions against a copy of the same data, SQL Server and HANA.
- Compare row counts and totals. If DocTotal sums or counts differ, find out why before moving on.
- Test edge cases. NULL values, cancelled documents, foreign currency and documents across a year end.
- Let key users sign off on the reports they use daily.
For starting points, our SAP B1 query library has common queries written in both T-SQL and HANA syntax, and the SQL to HANA converter speeds up the first pass on your own.
What to expect
Simple saved queries take minutes each. Formatted searches are similar. Reports with commands take longer because of testing. Stored procedures and the transaction notification take the most time and carry the most risk, so plan them first, not last.
If you are planning a move to HANA and want your queries, reports and validations converted and tested, contact Kodenova with a list of what you have.
Sources
- SAP (B1SA): Query Migration Tool for Microsoft SQL Server to SAP HANA (GitHub)
- SAP HANA SQL Reference: IFNULL Function
- SAP HANA SQL Reference: DAYS_BETWEEN Function
- SAP HANA SQL Reference: Datetime Functions
- SAP Community: How to convert an SAP B1 MS SQL Crystal Report to HANA
- SAP Community: SBO HANA query with user parameters
Related services
Frequently asked questions
Do SAP Business One queries work on HANA without changes?
Only the simplest ones. Any query that uses unquoted mixed-case column names, ISNULL, GETDATE, DATEADD, CONVERT or + for strings will fail or return wrong results on HANA. Queries built with the Query Generator usually need fewer changes.
Why does HANA say invalid column name when the column exists?
HANA converts unquoted identifiers to upper case. SAP Business One columns are mixed case, such as CardCode, so you must write T0."CardCode" with double quotes. Table names like OINV are already upper case, but quoting them too is a safe habit.
Do the [%0] parameters in saved queries still work on HANA?
Yes. The [%0], [%1] style parameters are handled by SAP Business One before the SQL reaches the database, so you keep them. Only the SQL around them has to change.
Is there a tool that converts T-SQL to HANA SQL automatically?
SAP published a Query Migration Tool on GitHub that converts much of T-SQL, but the project is archived and SAP says you must check the output. Our free SQL to HANA converter handles the common SAP B1 patterns. Either way, a person should test every converted query.
What is the hardest part of the migration?
Stored procedures, temp tables, cursors and SBO_SP_TransactionNotification. These need a proper SQLScript rewrite, not a find-and-replace.
Ready to get started?
Tell us what you need. You get a clear technical answer, a fixed scope and a price, usually within 24 hours.
