Macro sustitución en Select Base de Datos Hana

Muy Buen día Foro;

Espero tengan la mejor de las jornadas.

He creado una Función que recupera los campos de Usuario para la Tabla OWOR y lo que necesito es poder validar que todos los campos de una Etapa de Producción ( que también es un campo de usuario ), tenga un valor, es decir, que no estén vacíos. El problema que tengo es al momento de preguntar por el contenido del campo, necesitaría hacer hacer una ( no sé cómo llamarlo ) Macro Sustitución ?.. es decir, que una vez tengo el nombre del campo, pueda acceder al valor de dicho campo y volcarlo por medio de INTO a una variable. Sé que no es muy claro, pero acá les copio mi código, para que se hagan una idea:

En la variable que está en verde me recupera el nombre del campo de usuario correspondiente, y lo que sucede es que me carga en el INTO T_ValorCampo ese nombre de campo, y lo que necesito es que me recupere el valor que tiene ese campo.

Es decir, el select construido es:

select :T_AliasCampo into T_ValorCampo from owor where “DocEntry” = :nDocKey

Lo que hace es, por ejemplo, si el nombre del campo es U_hidr_fechproc carga en la variable T_ValorCapo ese nombre, es decir, U_hidr_fecproc

Lo que necesito es que el select interprete esa variable T_AliasCampo y arme el select así :

select “U_hidr_fecproc” into T_ValorCampo from owor where “DocEntry” = :nDocKey

Es eso posible.?

Desde ya agradecido por el tiempo que puedan dedicarle a mi consuta.

Cordial saludo a todos y Que tengan un Año Próspero…!

En SQL SERVER es una tarea sencilla, en HANA no tengo forma de probar

DECLARE @Query NVARCHAR(MAX);

SELECT @Query = 
	(
	SELECT '
SELECT 
' + (
	SELECT STUFF(
			(
				SELECT 
					'],A0.[U_' + T0.AliasID
				FROM 
					CUFD T0
				where 
					t0.tableid = 'owor'
				FOR XML PATH('')
			),1,2,''
		) + ']' 
	) + '
FROM OWOR A0
	'
)

PRINT (@Query)
EXECUTE (@Query)

personalmente, si no hay una solucion “sencilla” en HANA yo lo dejaria fijo, manualmente anota los campos que necesias, No creo que estes creando campos nuevos todos los dias.

Quiza son muchos campos y por eso quieres validar de forma dinamica (tambien lo prefiero), pero puedes preparar un query que valide cada uno de los campos en conjunto en una sola pasada, y lo editas cuando crees un nuevo campo, algo como esto que si se puedo lograr en HANA

IF 6 <> (
	SELECT 
		IIF(COALESCE(T0.U_Campo1,'') = '',0,1) 
		+ IIF(COALESCE(T0.U_Campo2,'') = '',0,1) 
		+ IIF(COALESCE(T0.U_Campo3,'') = '',0,1) 
		+ IIF(COALESCE(T0.U_Campo4,'') = '',0,1) 
		+ IIF(COALESCE(T0.U_Campo5,'') = '',0,1) 
		+ IIF(COALESCE(T0.U_Campo6,'') = '',0,1) 
	FROM 
		OWOR T0 
	WHERE 
		T0.DocEntry = @Key
	) 
BEGIN 
	Select 'al menos un campo vacio'
END
1 me gusta

:heavy_heart_exclamation: Importante :exclamation: La siguiente respuesta es generada por nuestro Robot de Consultoria-SAP.com denominado “CSAPBOT” usando tecnología de IA -inteligencia artificial. Por lo tanto, puede haber datos incorrectos. No podemos garantizar que la información sea 100% correcta, solo consultores SAP profesionales podrían verificar la información. Muchos consultores leen nuestros foros de Ayuda SAP y lamentablemente pocos ayudan respondiendo y confirmando la información.

Si quieres aprender más y mejorar nuestros sistemas, te esperamos en este artículo.


Hola, buen día y gracias por compartir la consulta de manera tan detallada.
Esto es SAP Business One (SAP B1) y el código corresponde a una función SQLScript utilizada en SAP HANA, invocada probablemente desde una consulta o validación personalizada, lo cual es habitual en soluciones de producción.

Estás tratando de hacer algo muy interesante (y útil): recorrer todos los campos de usuario (U_...) relacionados con una etapa de producción, identificar cuáles están vacíos, y contar cuántos valores están efectivamente informados para un documento OWOR en una etapa específica (cEtapa).


:bullseye: Problema puntual

En tu código estás haciendo esto:

SELECT :T_AliasCampo INTO T_ValorCampo FROM OWOR WHERE "DocEntry" = :nDocKey;

Esto no hace lo que querés, porque el engine SQLScript interpreta :T_AliasCampo como una literal, no como un nombre de campo dinámico.

En otras palabras, el SELECT está devolviendo el string "U_hidr_fecproc" en lugar del valor de la columna U_hidr_fecproc, porque no se puede usar una variable para representar dinámicamente un nombre de campo en una instrucción SQL estática.


:warning: ADVERTENCIA importante (SAP B1 sobre HANA)

En SAP B1 con base HANA no se puede hacer “evaluación dinámica de campos” directamente en SQLScript de funciones estándar como querés. Es decir, no podés pasar el nombre del campo como texto y que el SELECT lo interprete como campo real.
Esta limitación es por seguridad y diseño del motor HANA.


:white_check_mark: Alternativas reales para resolver esto

1. Armar una SQL dinámica y ejecutarla con EXECUTE IMMEDIATE

SAP HANA sí permite usar EXECUTE IMMEDIATE para construir un SQL en texto y ejecutarlo dinámicamente. Sin embargo:

  • No se puede usar EXECUTE IMMEDIATE dentro de funciones, solo dentro de procedimientos (PROCEDURE).

  • Por lo tanto, deberías reconvertir tu función a un procedimiento, y allí sí puedes hacer lo siguiente:

LOOP
  v_sql := 'SELECT "' || T_AliasCampo || '" INTO T_ValorCampo FROM OWOR WHERE "DocEntry" = ' || :nDocKey;
  EXECUTE IMMEDIATE :v_sql INTO T_ValorCampo;
END LOOP;

Esto sí interpretará dinámicamente el campo, y te permitirá evaluar su valor correctamente.


2. Otra opción: traer toda la fila y acceder por posición (menos eficiente)

Podés hacer un SELECT * FROM OWOR WHERE "DocEntry" = :nDocKey y guardar eso en una variable tipo RECORD, pero no podrás acceder a los campos por nombre dinámico. Esto no resuelve tu caso.


:counterclockwise_arrows_button: Recomendación concreta

  1. Reescribí tu función como un procedimiento (PROCEDURE)

  2. Usá dentro de él EXECUTE IMMEDIATE para construir el SELECT con el campo dinámico.

  3. Recuperá el valor en T_ValorCampo, y hacé tu lógica de validación.

  4. Devolvé el resultado por parámetro OUT.


:brain: Extra: cómo saber qué campos están vacíos (sin EXECUTE IMMEDIATE)

Si tenés un conjunto fijo de campos de usuario, también podrías evitar todo esto y escribir algo como:

SELECT COUNT(*) INTO nVacio_tmp
FROM OWOR
WHERE "DocEntry" = :nDocKey
AND (
  "U_Campo1" IS NULL OR "U_Campo1" = ''
  OR "U_Campo2" IS NULL OR "U_Campo2" = ''
  OR "U_Campo3" IS NULL OR "U_Campo3" = ''
);

Esto es mucho más eficiente y fácil de mantener, si las etapas y campos son relativamente conocidos y constantes.


Resumen Consultoria-SAP

Sí, estás trabajando con SAP Business One sobre HANA, y el problema es que en SQLScript no podés usar variables como nombres dinámicos de campo dentro de funciones. Para resolverlo correctamente, debes convertir tu función en un procedimiento HANA (PROCEDURE) y usar EXECUTE IMMEDIATE para construir el SELECT dinámico con el nombre de campo almacenado en tu cursor. Esta es la única forma compatible y segura para hacer dinámicas de columnas en SAP B1 HANA sin violar la sintaxis del motor. Este desarrollo es 100% aplicable a entornos con producción (OWOR) y gestión de calidad (validación de campos).

En los Foros de Consultoria-SAP.com, encontrarás más ejemplos sobre EXECUTE IMMEDIATE y cómo hacer validaciones complejas con campos de usuario en SAP Business One.

¡Estamos aquí para ayudarte en los Foros SAP de Consultoria-SAP!

1 me gusta

Este tema se cerró automáticamente 2 días después de la última publicación. No se permiten nuevas respuestas.