Migrar SAP Business One de SQL Server a HANA: cómo convertir sus consultas, reportes y búsquedas formateadas

Por Zain Abbas, Kodenova · Actualizado el

Respuesta cortaHANA usa SQL de estilo ANSI, así que la mayoría de las consultas de SAP Business One necesitan cambios pequeños pero estrictos: poner comillas a los nombres de columna (T0."CardCode"), cambiar ISNULL por IFNULL, GETDATE por CURRENT_TIMESTAMP, DATEADD y DATEDIFF por ADD_DAYS y DAYS_BETWEEN, CONVERT por TO_NVARCHAR, y + por || al concatenar cadenas. Las consultas simples se convierten en minutos. Los procedimientos almacenados, las tablas temporales y SBO_SP_TransactionNotification deben reescribirse en SQLScript y probarse con los mismos datos.

Por qué sus consultas fallan en HANA

Cuando una empresa migra SAP Business One de Microsoft SQL Server a SAP HANA, los datos pasan sin problemas. El SQL personalizado no. Las consultas guardadas, las alertas, las búsquedas formateadas, los comandos de Crystal Reports, el SQL de los add-ons y la notificación de transacciones llevan T-SQL. HANA no habla T-SQL.

La mayoría de los cambios son pequeños. El problema es que son muchos, y una sola comilla olvidada detiene toda la consulta. Esta guía enumera los cambios que hacemos con más frecuencia, en el orden en que los revisamos.

1. Ponga comillas a cada nombre de columna

Este es el cambio que atrapa a todo el mundo primero. HANA convierte a mayúsculas los nombres sin comillas. Los nombres de columna de SAP Business One combinan mayúsculas y minúsculas: CardCode, DocTotal, U_MyField. Así, T0.CardCode se convierte en T0.CARDCODE, y HANA no lo encuentra.

La solución son comillas dobles alrededor del nombre:

SELECT T0."DocNum", T0."CardCode", T0."DocTotal"
FROM "OINV" T0
WHERE T0."CANCELED" = 'N'

De aquí se derivan dos reglas:

  • Las comillas dobles indican un identificador. Las comillas simples indican una cadena. En SQL Server a veces se podía usar "N" sin problemas. En HANA, "N" es una columna llamada N, y la consulta falla.
  • Los alias también llevan comillas si quiere conservar sus mayúsculas y minúsculas: AS "Customer Name".

2. Cambie las funciones habituales

Estas son las funciones de T-SQL que vemos en casi todas las bases de datos de SAP B1, con sus equivalentes en HANA.

SQL Server (T-SQL)SAP HANANota
ISNULL(T0.Comments, '')IFNULL(T0."Comments", '')COALESCE funciona en ambos
GETDATE()CURRENT_TIMESTAMPUse CURRENT_DATE para la fecha sola
DATEADD(day, 30, T0.DocDate)ADD_DAYS(T0."DocDate", 30)También ADD_MONTHS, ADD_YEARS
DATEDIFF(day, T0.DocDueDate, GETDATE())DAYS_BETWEEN(T0."DocDueDate", CURRENT_DATE)Mismo orden de argumentos: desde, hasta
CONVERT(varchar, T0.DocDate, 103)TO_NVARCHAR(T0."DocDate", 'DD/MM/YYYY')Una cadena de formato reemplaza el número de estilo
T0.CardCode + ' - ' + T0.CardNameT0."CardCode" || ' - ' || T0."CardName"En HANA, + solo suma números
SELECT TOP 10 ...SELECT TOP 10 ... o LIMIT 10TOP funciona en HANA
#Temp / SELECT INTOVariable de tabla o CREATE LOCAL TEMPORARY TABLERequiere SQLScript
SELECT GETDATE()SELECT CURRENT_TIMESTAMP FROM DUMMYHANA necesita una cláusula FROM
RIGHT(REPLICATE('0', 8) + T0.CardCode, 8)LPAD(T0."CardCode", 8, '0')Relleno con ceros; RPAD rellena por la derecha. Un REPLICATE('-', 10) suelto pasa a ser LPAD('', 10, '-')

Un ejemplo completo de antes y después, a partir de una consulta típica de facturas vencidas:

-- 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

Puede pegar su propio T-SQL en nuestro conversor gratuito de SQL a HANA para obtener un primer borrador de estos cambios.

3. Mantenga los parámetros de B1 tal como están

Las consultas guardadas que piden datos al usuario usan [%0], [%1], etc. SAP Business One los reemplaza antes de que el SQL llegue a la base de datos, así que en HANA se quedan igual:

SELECT T0."DocNum", T0."DocDate", T0."DocTotal"
FROM "ORDR" T0
WHERE T0."DocDate" >= [%0]
  AND T0."DocDate" <= [%1]

Las búsquedas formateadas funcionan de la misma manera. Las referencias como $[$38.1.0] o $[ORDR."CardCode"] las rellena el cliente. Solo hay que convertir el SQL que las rodea. Cuidado con las comillas dentro de la referencia de campo: la tabla y la columna siguen las mismas reglas de HANA.

4. Los procedimientos almacenados y las tablas temporales necesitan SQLScript

Aquí el buscar y reemplazar deja de funcionar. Los procedimientos de T-SQL usan @variables, tablas #temp, SELECT INTO, bucles WHILE y cursores. Los procedimientos de HANA se escriben en SQLScript, que tiene otra forma:

  • Las variables se declaran con DECLARE y se leen con el prefijo dos puntos: :lv_total.
  • Los resultados intermedios suelen ir en variables de tabla (lt_open = SELECT ...;), no en tablas temporales.
  • HANA sí tiene tablas temporales locales (también nombradas con #), pero primero hay que crearlas con columnas explícitas. No existe SELECT INTO #temp.
  • Cada sentencia termina con punto y coma.
-- 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;

Los scripts de T-SQL que ejecuta a mano con DECLARE @x al principio no tienen un equivalente directo en HANA fuera de un procedimiento. Envuélvalos en un bloque anónimo, DO BEGIN ... END;, que ejecuta SQLScript una vez sin crear un procedimiento:

-- 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;

Los bloques anónimos admiten las mismas sentencias que el cuerpo de un procedimiento, pero no se pueden usar dentro de un procedimiento o una función.

Vale la pena rediseñar los procedimientos cargados de cursores como consultas basadas en conjuntos aprovechando la migración. HANA lo recompensa.

5. SBO_SP_TransactionNotification

En HANA, SAP Business One entrega la notificación de transacciones como un procedimiento SQLScript. Recibe las mismas entradas que antes (tipo de objeto, tipo de transacción, columnas clave y valores) y devuelve al final el código y el mensaje de error con un SELECT ... FROM DUMMY. Para ver reglas completas en paralelo, consulte estos ejemplos de TransactionNotification para SQL Server y HANA.

Sus bloques de validación en T-SQL deben reescribirse dentro de ese procedimiento. Un bloque típico se ve así:

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 al principio del procedimiento. Mantenga cada regla pequeña y pruebe la creación y la actualización por separado. Cuando una regla bloquea un documento que contabiliza una integración, la llamada a DI API o Service Layer falla y su mensaje vuelve en el texto del error; cómo leerlo se explica en códigos de error de DI API. Un solo error de sintaxis aquí bloquea todos los documentos de la empresa, así que despliéguelo fuera del horario laboral.

6. Comandos de Crystal Reports

Los Crystal Reports creados sobre SQL Server suelen usar un Command (una sentencia SQL pegada) o llamar a un procedimiento almacenado. Ambos llevan T-SQL. Para cada reporte:

  1. Convierta el SQL del comando o el procedimiento a sintaxis de HANA.
  2. Apunte el reporte al origen de datos de HANA con Database > Set Datasource Location, usando la conexión, las credenciales y el esquema de la empresa en HANA.
  3. Compruebe que los campos de parámetro siguen asignados a los parámetros del comando.
  4. Previsualícelo en el cliente de SAP Business One para HANA y compare el resultado con la versión de SQL Server.

Los reportes creados sobre tablas sin comandos normalmente solo necesitan el paso 2.

7. Un enfoque de pruebas que detecta errores

Que una consulta convertida se ejecute no significa que sea correcta. La concatenación de cadenas con + es la trampa clásica: en HANA puede fallar o puede intentar sumar los valores como números. Los formatos de fecha son otra.

  1. Primero el inventario. Exporte la lista de consultas guardadas (OUQR), búsquedas formateadas (CSHS), alertas, reportes de Crystal, procedimientos de usuario y la notificación de transacciones. Anote quién usa cada uno. Muchos no se usarán y se pueden descartar.
  2. Convierta por lotes según el tipo: consultas simples, búsquedas formateadas, reportes y después procedimientos.
  3. Ejecute ambas versiones sobre una copia de los mismos datos, en SQL Server y en HANA.
  4. Compare número de filas y totales. Si las sumas de DocTotal o los conteos difieren, averigüe por qué antes de seguir.
  5. Pruebe los casos límite. Valores NULL, documentos cancelados, moneda extranjera y documentos que cruzan un cierre de año.
  6. Pida a los usuarios clave que aprueben los reportes que usan a diario.

Como punto de partida, nuestra biblioteca de consultas SAP B1 tiene consultas habituales escritas tanto en T-SQL como en sintaxis de HANA, y el conversor de SQL a HANA acelera la primera pasada sobre las suyas.

Qué esperar

Las consultas guardadas simples llevan minutos cada una. Las búsquedas formateadas, algo parecido. Los reportes con comandos llevan más tiempo por las pruebas. Los procedimientos almacenados y la notificación de transacciones son los que más tiempo consumen y más riesgo conllevan, así que planifíquelos primero, no al final.

Si está planificando una migración a HANA y quiere que sus consultas, reportes y validaciones se conviertan y se prueben, contacte con Kodenova con una lista de lo que tiene.

Fuentes

Servicios relacionados

Preguntas frecuentes

Preguntas frecuentes

¿Funcionan las consultas de SAP Business One en HANA sin cambios?

Solo las más simples. Cualquier consulta que use nombres de columna con mayúsculas y minúsculas sin comillas, ISNULL, GETDATE, DATEADD, CONVERT o + para cadenas fallará o devolverá resultados incorrectos en HANA. Las consultas creadas con el generador de consultas suelen necesitar menos cambios.

¿Por qué HANA dice invalid column name (nombre de columna no válido) si la columna existe?

HANA convierte a mayúsculas los identificadores sin comillas. Las columnas de SAP Business One combinan mayúsculas y minúsculas, como CardCode, así que debe escribir T0."CardCode" con comillas dobles. Los nombres de tabla como OINV ya están en mayúsculas, pero ponerles comillas también es un hábito seguro.

¿Siguen funcionando en HANA los parámetros [%0] de las consultas guardadas?

Sí. SAP Business One procesa los parámetros del estilo [%0], [%1] antes de que el SQL llegue a la base de datos, así que se mantienen. Solo hay que cambiar el SQL que los rodea.

¿Existe una herramienta que convierta T-SQL a SQL de HANA automáticamente?

SAP publicó en GitHub una Query Migration Tool que convierte buena parte del T-SQL, pero el proyecto está archivado y SAP indica que hay que revisar el resultado. Nuestro conversor gratuito de SQL a HANA resuelve los patrones habituales de SAP B1. En cualquier caso, una persona debe probar cada consulta convertida.

¿Cuál es la parte más difícil de la migración?

Los procedimientos almacenados, las tablas temporales, los cursores y SBO_SP_TransactionNotification. Necesitan una reescritura real en SQLScript, no un buscar y reemplazar.

¿Listo para empezar?

Cuéntenos lo que necesita. Recibirá una respuesta técnica clara, un alcance definido y un precio fijo, normalmente en 24 horas.