7

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

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

谁能帮我写这个函数EvaluateExpression

目前我正在使用我需要避免的 CLR 函数。

编辑1

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

我还有大约 400,000 个这样的公式需要评估。

编辑2

我知道我们可以使用函数内部的 osql.exe 来做到这一点,如此所述。但由于权限设置,我也不能使用它。

4

4 回答 4

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,如execor sp_executesql,在用户定义的函数中是不允许的。

于 2012-03-24T10:21:03.110 回答
3

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

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

性能很棒(比 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()
于 2016-02-09T21:51:48.320 回答
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')
于 2012-03-24T11:06:20.333 回答
0

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

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

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

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

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

  • 包含要在公式中使用的 n 行的数据表称为 tab_value

  • 我必须使用 SQL 游标将在 n 行(在 tab_values 中)中找到的 n 个值存储在一个新表中的一行中,

  • 为此,我创建了一个名为 tab_formula 的新表

  • 在光标中,我将为每个值添加一个新列,列名将是 Id1、Id2、Id3 等。

  • 然后我构建一个包含公式的 SQL 脚本来评估公式

在完成脚本之后,希望您觉得它有用,欢迎您向我询问。

该过程用作输入:

-公式

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

if exists(select 1 from sysobjects where name='usp_evaluate_formula' and xtype='p') 

drop proc usp_evaluate_formula 

go

create type type_tab as table(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 

declare @tab_values table (id int, val decimal(10,2))

insert into @tab_values(id,val) select * from @values

declare @id as int declare @val as decimal(10,2)
if not exists(select 1 from sysobjects where name ='tab_formula') 
create table tab_formula(id int identity(1,1), formula nvarchar(1000))

if not exists(select 1 from tab_formula where formula=@formula) 
insert into tab_formula(formula) values(@formula)


declare c cursor for select id,val from @tab_values 

declare @script as nvarchar(4000) 

open c 

fetch c into @id,@val 

while @@fetch_status=0 

begin 

set @script = 'if not exists(select 1 from syscolumns c inner join sysobjects o on c.id=o.id where o.name=''tab_formula'' and c.name=''id'+
convert(nvarchar(3),@id)+ ''') 
alter table tab_formula add 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+') "Result" from tab_formula where formula='''+@formula+'''' 

print @script 

exec(@script)

end

go

declare @mytab as type_tab 

insert into @mytab(val) values(1.56),(1.5) ,(2.5) ,(32),(1.7) ,(3.3) ,(3.9)

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

go 
drop proc usp_evaluate_formula 

drop type type_tab 

drop table tab_formula
于 2016-08-31T17:08:43.273 回答