miércoles, 17 de septiembre de 2014

Parsear Fórmulas o Queries en SQL Server 2008

Este Procedimiento Almacenado, parsea una formula o ejecuta un query y regresa el resultado en un decimal, en caso de que no pueda parsear o ejecutar el comando, regresará NULL.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: YoRcH
-- Create date: 25 JUN 2010
-- Description: Parsear Formulas para Nomina
-- =============================================
ALTER PROCEDURE [Global].[usp_parseFormula] 
@CFORMULA NVARCHAR(MAX)
   ,@CXML NVARCHAR(MAX)
   ,@nResultado DECIMAL(12,2) OUTPUT
AS

BEGIN

DECLARE @CVARIABLE AS VARCHAR(MAX)
DECLARE @NVALOR AS DECIMAL(12,2)
DECLARE @nXmlDoc INT
DECLARE @Parametros NVARCHAR(255)
DECLARE @rc INT

SET @CXML = '' + @CXML + '' -- CERRAR TABLA DE VARIABLES XML

-- Cargar XML de Variables
EXEC sp_xml_preparedocument @nXmlDoc OUTPUT, @CXML

BEGIN TRY
-- Crear Cursor
DECLARE Cur_Variables CURSOR LOCAL FORWARD_ONLY FOR 
SELECT VARIABLE, VALOR
FROM OPENXML (@nXmlDoc, '/ROOT/TVARIABLES',2)
WITH (VARIABLE varchar (255), VALOR DECIMAL(12,2))

OPEN Cur_Variables
FETCH Cur_Variables INTO @CVARIABLE, @NVALOR

WHILE (@@FETCH_STATUS = 0) BEGIN -- Ciclo de Variables
SET @CFORMULA = REPLACE (@CFORMULA, @CVARIABLE, @NVALOR)

FETCH Cur_Variables INTO @CVARIABLE, @NVALOR
END

CLOSE Cur_Variables
DEALLOCATE Cur_Variables

SET @Parametros = '@nResultado DECIMAL(12,2) OUTPUT';
SET @CFORMULA = 'SELECT @nResultado = (' + @CFORMULA + ')'

SET @CFORMULA = REPLACE (@CFORMULA, '--', '+') -- QUITAR SIGNOS DE -

-- Parsear Formula
BEGIN TRY 
 EXEC @rc = sp_executesql @CFORMULA, @Parametros, @nResultado OUTPUT;

 IF @rc <> 0 BEGIN
SET @nResultado = NULL
 END
END TRY
BEGIN CATCH
SET @nResultado = NULL
END CATCH
END TRY
BEGIN CATCH
SET @nResultado = NULL
END CATCH

EXECUTE sp_xml_removedocument @nXmlDoc

END -- SP

Ejemplo de Uso:

DECLARE @RC int
DECLARE @CFORMULA nvarchar(max)
DECLARE @CXML nvarchar(max)
DECLARE @nResultado decimal(12,2)

DECLARE @tVariables Table (VARIABLE varchar (255), VALOR DECIMAL(12,2))

INSERT INTO @tVariables VALUES ('W', 2)
INSERT INTO @tVariables VALUES ('X', -2)
INSERT INTO @tVariables VALUES ('Y', -3)
INSERT INTO @tVariables VALUES ('Z', 5)

-- PASAR TABLA A XML
SET @CXML = (SELECT VARIABLE
  ,VALOR
FROM @tVariables AS TVARIABLES
FOR XML AUTO, ELEMENTS)  


EXECUTE @RC = [Global].[usp_parseFormula] '(X-Y-Z-W)*-W', @CXML, @nResultado OUTPUT

SELECT @nResultado AS RESULTADO

El resultado es 12.00.

Solo se debe definir una nomenclatura correcta para los nombre de las variables, para que no se traslapen con nombres de columnas o funciones.

No hay comentarios: