Migrare SAP Business One da SQL Server a HANA: come convertire query, report e ricerche formattate
By Zain Abbas, Kodenova · Updated
Perché le query si bloccano su HANA
Quando un’azienda sposta SAP Business One da Microsoft SQL Server a SAP HANA, i dati migrano senza problemi. L’SQL personalizzato no. Query salvate, alert, ricerche formattate, comandi di Crystal Reports, SQL degli add-on e transaction notification contengono tutti T-SQL, e HANA non parla T-SQL.
La maggior parte delle modifiche è piccola. Il problema è che sono tante, e una sola virgoletta dimenticata blocca l’intera query. Questa guida elenca le modifiche che facciamo più spesso, nell’ordine in cui le verifichiamo.
1. Mettere le virgolette a ogni nome di colonna
È la modifica che coglie tutti di sorpresa per prima. HANA converte in maiuscolo i nomi senza virgolette. I nomi delle colonne di SAP Business One hanno maiuscole e minuscole: CardCode, DocTotal, U_MyField. Così T0.CardCode diventa T0.CARDCODE e HANA non lo trova.
La soluzione sono le virgolette doppie intorno al nome:
SELECT T0."DocNum", T0."CardCode", T0."DocTotal"
FROM "OINV" T0
WHERE T0."CANCELED" = 'N'
Ne derivano due regole:
- Le virgolette doppie indicano un identificatore. Gli apici singoli indicano una stringa. In SQL Server a volte si poteva scrivere
"N"; su HANA"N"è una colonna chiamata N e la query fallisce. - Anche gli alias vanno tra virgolette se vuole mantenerne le maiuscole:
AS "Customer Name".
2. Sostituire le funzioni più comuni
Queste sono le funzioni T-SQL che troviamo in quasi ogni database SAP B1, con i loro equivalenti HANA.
| SQL Server (T-SQL) | SAP HANA | Nota |
|---|---|---|
ISNULL(T0.Comments, '') | IFNULL(T0."Comments", '') | COALESCE funziona su entrambi |
GETDATE() | CURRENT_TIMESTAMP | Usi CURRENT_DATE per la sola data |
DATEADD(day, 30, T0.DocDate) | ADD_DAYS(T0."DocDate", 30) | Esistono anche ADD_MONTHS, ADD_YEARS |
DATEDIFF(day, T0.DocDueDate, GETDATE()) | DAYS_BETWEEN(T0."DocDueDate", CURRENT_DATE) | Stesso ordine degli argomenti: da, a |
CONVERT(varchar, T0.DocDate, 103) | TO_NVARCHAR(T0."DocDate", 'DD/MM/YYYY') | La stringa di formato sostituisce il numero di stile |
T0.CardCode + ' - ' + T0.CardName | T0."CardCode" || ' - ' || T0."CardName" | Su HANA + somma solo numeri |
SELECT TOP 10 ... | SELECT TOP 10 ... oppure LIMIT 10 | TOP funziona su HANA |
#Temp / SELECT INTO | Variabile di tabella o CREATE LOCAL TEMPORARY TABLE | Richiede SQLScript |
SELECT GETDATE() | SELECT CURRENT_TIMESTAMP FROM DUMMY | HANA richiede una clausola FROM |
RIGHT(REPLICATE('0', 8) + T0.CardCode, 8) | LPAD(T0."CardCode", 8, '0') | Riempimento con zeri; RPAD riempie a destra. Un semplice REPLICATE('-', 10) diventa LPAD('', 10, '-') |
Un esempio completo prima e dopo, da una tipica query sulle fatture scadute:
-- 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
Può incollare il suo T-SQL nel nostro convertitore gratuito da SQL a HANA per ottenere una prima bozza di queste modifiche.
3. Lasciare invariati i parametri di B1
Le query salvate che chiedono un input all’utente usano [%0], [%1] e così via. SAP Business One li sostituisce prima che l’SQL arrivi al database, quindi su HANA restano uguali:
SELECT T0."DocNum", T0."DocDate", T0."DocTotal"
FROM "ORDR" T0
WHERE T0."DocDate" >= [%0]
AND T0."DocDate" <= [%1]
Le ricerche formattate funzionano allo stesso modo. Riferimenti come $[$38.1.0] o $[ORDR."CardCode"] vengono compilati dal client. Va convertito solo l’SQL che li circonda. Faccia attenzione alle virgolette dentro il riferimento al campo: tabella e colonna seguono le stesse regole di HANA.
4. Stored procedure e tabelle temporanee richiedono SQLScript
Qui il trova e sostituisci smette di funzionare. Le procedure T-SQL usano @variabili, tabelle #temp, SELECT INTO, cicli WHILE e cursori. Le procedure HANA si scrivono in SQLScript, che ha una struttura diversa:
- Le variabili si dichiarano con
DECLAREe si leggono con il prefisso dei due punti::lv_total. - I risultati intermedi di solito finiscono in variabili di tabella (
lt_open = SELECT ...;), non in tabelle temporanee. - HANA ha tabelle temporanee locali (anch’esse con
#nel nome), ma vanno prima create con colonne esplicite. Non esisteSELECT INTO #temp. - Ogni istruzione termina con un punto e virgola.
-- 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;
Gli script T-SQL eseguiti a mano con DECLARE @x in cima non hanno un equivalente HANA diretto fuori da una procedura. Li racchiuda in un blocco anonimo, DO BEGIN ... END;, che esegue SQLScript una volta senza creare una procedura:
-- 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;
I blocchi anonimi supportano le stesse istruzioni del corpo di una procedura, ma non si possono usare dentro una procedura o una funzione.
Già che ci si trova, conviene riprogettare le procedure piene di cursori come query basate su insiemi. HANA ne trae vantaggio.
5. SBO_SP_TransactionNotification
Su HANA, SAP Business One fornisce la transaction notification come procedura SQLScript. Riceve gli stessi input di prima (tipo di oggetto, tipo di transazione, colonne chiave e valori) e alla fine restituisce codice e messaggio di errore con una SELECT ... FROM DUMMY. Per le regole complete a confronto, veda questi esempi di TransactionNotification per SQL Server e HANA.
I blocchi di validazione T-SQL vanno riscritti all’interno di quella procedura. Un blocco tipico si presenta così:
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;
Dichiari cnt all’inizio della procedura. Mantenga ogni regola piccola e testi separatamente inserimento e modifica. Quando una regola blocca un documento registrato da un’integrazione, la chiamata DI API o Service Layer fallisce e il suo messaggio torna nel testo dell’errore; come leggerlo è spiegato in codici di errore della DI API. Un solo errore di sintassi qui blocca tutti i documenti della società, quindi la distribuisca fuori dall’orario di lavoro.
6. Comandi di Crystal Reports
I Crystal Reports costruiti su SQL Server usano spesso un Command (un’istruzione SQL incollata) o richiamano una stored procedure. Entrambi contengono T-SQL. Per ogni report:
- Converta l’SQL del comando o la procedura nella sintassi HANA.
- Punti il report alla fonte dati HANA con Database > Set Datasource Location, usando la connessione HANA, le credenziali e lo schema della società.
- Verifichi che i campi parametro corrispondano ancora ai parametri del comando.
- Visualizzi l’anteprima nel client SAP Business One per HANA e confronti il risultato con la versione SQL Server.
I report basati su semplici tabelle, senza comandi, di solito richiedono solo il passo 2.
7. Un approccio di test che intercetta gli errori
Una query convertita che gira non equivale a una query convertita corretta. La concatenazione di stringhe con + è la trappola classica: su HANA può fallire oppure tentare di sommare i valori come numeri. I formati delle date sono un’altra.
- Prima l’inventario. Esporti l’elenco di query salvate (OUQR), ricerche formattate (CSHS), alert, report Crystal, procedure utente e transaction notification. Annoti chi usa ciascun elemento. Molti risulteranno inutilizzati e si potranno eliminare.
- Converta a lotti per tipo: query semplici, ricerche formattate, report, poi procedure.
- Esegua entrambe le versioni su una copia degli stessi dati, SQL Server e HANA.
- Confronti numero di righe e totali. Se le somme di DocTotal o i conteggi differiscono, scopra perché prima di proseguire.
- Testi i casi limite. Valori NULL, documenti annullati, valuta estera e documenti a cavallo di fine anno.
- Faccia approvare agli utenti chiave i report che usano ogni giorno.
Come punto di partenza, la nostra libreria di query SAP B1 contiene query comuni scritte sia in sintassi T-SQL sia HANA, e il convertitore da SQL a HANA accelera il primo passaggio sulle sue.
Che cosa aspettarsi
Le query salvate semplici richiedono pochi minuti ciascuna. Le ricerche formattate sono simili. I report con comandi richiedono più tempo per via dei test. Stored procedure e transaction notification richiedono più tempo e comportano più rischi, quindi le pianifichi per prime, non per ultime.
Se sta pianificando il passaggio a HANA e vuole che query, report e validazioni vengano convertiti e testati, contatti Kodenova con l’elenco di ciò che ha.
Sources
- SAP (B1SA): Query Migration Tool for Microsoft SQL Server to SAP HANA (GitHub)
- SAP HANA SQL Reference: IFNULL Function
- SAP HANA SQL Reference: LPAD Function (String)
- SAP HANA SQLScript Reference: Anonymous Block
- SAP HANA SQL Reference: DAYS_BETWEEN Function
- SAP HANA SQL Reference: Datetime Functions
- SAP Community: come convertire un Crystal Report di SAP B1 da MS SQL a HANA
- SAP Community: query SBO su HANA con parametri utente
Related services
Frequently asked questions
Le query di SAP Business One funzionano su HANA senza modifiche?
Solo le più semplici. Qualsiasi query che usa nomi di colonna con maiuscole e minuscole senza virgolette, ISNULL, GETDATE, DATEADD, CONVERT o + per le stringhe fallirà o darà risultati errati su HANA. Le query create con il Query Generator di solito richiedono meno modifiche.
Perché HANA segnala un nome di colonna non valido se la colonna esiste?
HANA converte in maiuscolo gli identificatori senza virgolette. Le colonne di SAP Business One hanno maiuscole e minuscole, come CardCode, quindi deve scrivere T0."CardCode" con le virgolette doppie. I nomi di tabella come OINV sono già in maiuscolo, ma mettere le virgolette anche a questi è una buona abitudine.
I parametri [%0] delle query salvate funzionano ancora su HANA?
Sì. I parametri di tipo [%0], [%1] vengono gestiti da SAP Business One prima che l'SQL arrivi al database, quindi li può mantenere. Va modificato solo l'SQL che li circonda.
Esiste uno strumento che converte automaticamente il T-SQL in SQL HANA?
SAP ha pubblicato su GitHub un Query Migration Tool che converte buona parte del T-SQL, ma il progetto è archiviato e SAP avverte che il risultato va verificato. Il nostro convertitore gratuito da SQL a HANA gestisce gli schemi più comuni di SAP B1. In ogni caso, una persona dovrebbe testare ogni query convertita.
Qual è la parte più difficile della migrazione?
Stored procedure, tabelle temporanee, cursori e SBO_SP_TransactionNotification. Richiedono una vera riscrittura in SQLScript, non un trova e sostituisci.
Iniziamo?
Ci descriva di cosa ha bisogno. Riceverà una risposta tecnica chiara, un perimetro definito e un prezzo, di norma entro 24 ore.
