我正在尝试找到一种解决方法来计算 SQL Server 中的字符串,就像 JavaScript 上的
eval()
函数一样。困难的是我需要它在函数中执行此操作,以便我可以在存储过程的查询中使用它。
Supply = '2 + 2 * 3'
Demand = '2'
SELECT Name, CAST(dbo.CalculateString(Supply) * Demand AS DECIMAL(18, 1)) AS CalculatedValue FROM Stocks;
the expected output is
Candy 16
我明白了:
有什么解决办法吗?我正在使用 SQL Server 16.0.1000.6
可以吗?是的
你想做吗?不
让我示范一下。
首先让我们创建一些示例数据:
CREATE TABLE Stocks( ID INT IDENTITY, Supply VARCHAR( 50 ), Demand VARCHAR( 50 ))
INSERT INTO Stocks( Supply, Demand )
SELECT '2 + 2 * 3', '2'
UNION ALL
SELECT '2 - 2 * 3', '2 / 2'
现在,我们创建将动态评估您的列的过程(请注意,过程已适当命名):
CREATE OR ALTER PROCEDURE DirtyHack
AS
SET NOCOUNT ON;
DECLARE @ID INT, @Supply VARCHAR( 50 ), @Demand VARCHAR( 50 )
DECLARE @EvalQuery NVARCHAR( 500 ), @EvaluatedSupply INT, @EvaluatedDemand INT
CREATE TABLE #Result( ID INT, EvaluatedSupply INT, EvaluatedDemand INT )
DECLARE iterator CURSOR LOCAL FAST_FORWARD
FOR SELECT ID, Supply, Demand FROM Stocks
OPEN iterator
FETCH NEXT FROM iterator INTO @ID, @Supply, @Demand
WHILE @@FETCH_STATUS = 0
BEGIN
SET @EvalQuery = N'SET @EvaluatedSupply = ' + @Supply + '; SET @EvaluatedDemand = ' + @Demand + ';'
EXEC sp_executesql @EvalQuery, N'@EvaluatedSupply INT OUTPUT, @EvaluatedDemand INT OUTPUT',
@EvaluatedSupply = @EvaluatedSupply OUTPUT, @EvaluatedDemand = @EvaluatedDemand OUTPUT
INSERT INTO #Result
SELECT @ID, @EvaluatedSupply, @EvaluatedDemand
FETCH NEXT FROM iterator INTO @ID, @Supply, @Demand
END
CLOSE iterator
DEALLOCATE iterator
SELECT ID, EvaluatedSupply, EvaluatedDemand FROM #Result
RETURN;
该过程非常简单:使用游标循环遍历每一行并动态评估列,然后将结果存储到临时表中。对于更大的桌子,性能将会很缓慢。
然后我们使用
OPENQUERY
技巧将这个存储过程转换为视图:
CREATE OR ALTER VIEW VeryDirtyHack
AS
SELECT *
FROM OPENQUERY( SELF, 'EXEC Playground.dbo.DirtyHack WITH RESULT SETS(( ID INT, EvaluatedSupply INT, EvaluatedDemand INT ))' ) AS Eval;
SELF
是指向自身的链接服务器的名称。 WITH RESULT SETS
对于避免 SQL Server 对结果集的格式感到困惑是必要的。
您可以创建一个函数来代替视图,但这不会对功能产生任何影响。
现在你可以这样做:
SELECT *, EvaluatedSupply * EvaluatedDemand AS CalculatedValue
FROM Stocks AS S
INNER JOIN VeryDirtyHack AS VDH ON S.ID = VDH.ID
结果:
ID Supply Demand ID EvaluatedSupply EvaluatedDemand CalculatedValue
----------- ---------- ------- --- --------------- --------------- ---------------
1 2 + 2 * 3 2 1 8 2 16
2 2 - 2 * 3 2 / 2 2 -4 1 -4
这在 SQL Server 中是最“hacky”的。由于过程中执行 RBAR,性能会受到影响。由于无法将参数传递给
OPENQUERY
函数,因此无法“优化”存储过程。