字符串表达式要计算为数字

问题描述 投票:7回答:5

我需要编写一个SQL用户定义的函数,它将接受一个字符串并返回一个数字。

我将调用像dbo.EvaluateExpression('10*4.5*0.5')这样的函数应该返回数字22.5

任何人都可以帮我写这个函数EvaluateExpression

目前我正在使用CLR功能,我需要避免。

EDIT1

我知道这可以使用存储过程完成,但我想在一些语句ex:select 10* dbo.EvaluateExpression('10*4.5*0.5')中调用此函数

此外,我有大约400,000个像这样的公式进行评估。

Aaditi

我知道我们可以使用osql.exe内部函数来解决here。但由于权限设置,我也不能使用它。

sql-server tsql evaluate
5个回答
6
投票

我认为在用户定义的函数中不可能。

您可以在存储过程中执行此操作,例如:

declare @calc varchar(max)
set @calc = '10*4.5*0.5'

declare @sql nvarchar(max)
declare @result float
set @sql = N'set @result = ' + @calc
exec sp_executesql @sql, N'@result float output', @result out
select @result

但是在用户定义的函数中不允许使用动态SQL,如execsp_executesql


3
投票

免责声明:我是Eval SQL.NET项目的所有者

对于SQL 2012+,您可以使用可以使用SAFE权限运行的Eval SQL.NET。

性能很好(优于UDF)并且尊重运算符优先级和括号。事实上,几乎所有的C#语言都受支持。

您还可以为公式指定参数。

-- SELECT 225.00
SELECT 10 * CAST(SQLNET::New('10*4.5*0.5').Eval() AS DECIMAL(18, 2))

-- SELECT 70
DECLARE @formula VARCHAR(50) = 'a+b*c'
SELECT  10 * SQLNET::New(@formula)
                    .Val('a', 1)
                    .Val('b', 2)
                    .Val('c', 3)
                    .EvalInt()

0
投票

使用此功能,绝对有效。

CREATE FUNCTION dbo.EvaluateExpression(@list nvarchar(MAX))

RETURNS Decimal(10,2)
AS

BEGIN
Declare @Result Decimal(10,2)
set @Result=1
 DECLARE @pos        int,
       @nextpos    int,
       @valuelen   int

SELECT @pos = 0, @nextpos = 1


WHILE @nextpos > 0
  BEGIN
     SELECT @nextpos = charindex('*', @list, @pos + 1)
     SELECT @valuelen = CASE WHEN @nextpos > 0
                             THEN @nextpos
                             ELSE len(@list) + 1
                        END - @pos - 1

                        Set @Result=@Result*convert(decimal(10,2),substring(@list, @pos + 1, @valuelen))


     SELECT @pos = @nextpos
  END

RETURN @Result
END

你可以用它

Select 10* dbo.EvaluateExpression('10*4.5*0.5')

0
投票

您可以使用下面的SQL存储过程来计算包含任意数量变量的任何公式的结果:

我在2012年写了一个解决方案,它可以使用SQL SERVER评估任何类型的数学公式。该解决方案可以使用N个变量处理任何公式:

我被要求找到一种方法来评估由用户填写的公式给出的值。公式包含数学运算(加法,乘法,除法和减法)用于计算公式的参数存储在SQL服务器数据库中。

我自己找到的解决方案如下:

假设我有n个参数用于计算公式,这些参数中的每一个都存储在一个数据表的一行中。

  • 包含要在公式中使用的n行的数据表称为tab_value
  • 我必须使用SQL游标将n行中的n个值(在tab_values中)存储在一个新表中的一行中,
  • 为此,我创建了一个名为tab_formula的新表
  • 在光标中,我将为每个值添加一个新列,列名称将为Id1,Id2,Id3等。
  • 然后我构造一个包含公式的SQL脚本来评估公式

在完整的脚本之后,我希望你发现它很有用,欢迎你向我询问。

该过程用作输入:

-公式

- 包含用于计算公式的值的表

如果存在(从sysobjects中选择1,其中name ='usp_evaluate_formula'和xtype ='p')drop proc usp_evaluate_formula go

创建类型type_tab作为表(id int identity(1,1),val decimal(10,2))go create proc usp_evaluate_formula(@formula as nvarchar(100),@ values as type_tab readonly)as begin --KAMEL GAZZAH - [email protected] - 05/09/2016

声明@tab_values表(id int,val decimal(10,2))

从@tab_values中删除插入@tab_values(id,val)从@values中选择*

声明@id为int声明@val为十进制(10,2)

如果不存在(从sysobjects中选择1,其中name ='tab_formula')创建表tab_formula(id int identity(1,1),formula nvarchar(1000))如果不存在(从tab_formula中选择1,其中formula = @ formula)insert into tab_formula(公式)值(@formula)

声明c cursor为select id,val来自@tab_values声明@script为nvarchar(4000)open c fetch c into @ id,@ val而@@ fetch_status = 0 begin set @script ='if not exists(从syscolumns c中选择1)内联接sysobjects o在c.id = o.id其中o.name =''tab_formula''和c.name =''id'+ convert(nvarchar(3),@ id)+''')alter table tab_formula添加id'+ convert(nvarchar(3),@ id)+'decimal(10,2)'print @script exec(@script)set @ script ='update tab_formula set id'+ convert(nvarchar(3),@ id)+'='+ convert(nvarchar(10),@ val)+'where formula ='''+ @ formula +''''print @script exec(@script)fetch c into @ id,@ val end close c deallocate c

set @ script ='select *,convert(decimal(10,2),'+ @ formula +')“tab_formula中的”结果“,其中formula ='''+ @ formula +''''print @script exec(@script)

结束

将@mytab声明为type_tab插入@mytab(val)值(1.56)插入@mytab(val)值(15)插入@mytab(val)值(25)插入@mytab(val)值(32)insert进入@mytab(val)值(17)插入@mytab(val)值(33)插入@mytab(val)值(37.9)

exec usp_evaluate_formula'cos(id1)+ cos(id2)+ cos(id3)+ cos(id4)+ cos(id5)+ cos(id6)+ cos(id7)/ cos(Id6)',@ mytab

go drop proc usp_evaluate_formula drop type type_tab drop table tab_formula

© www.soinside.com 2019 - 2024. All rights reserved.