我需要编写一个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。但由于权限设置,我也不能使用它。
我认为在用户定义的函数中不可能。
您可以在存储过程中执行此操作,例如:
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,如exec
或sp_executesql
。
免责声明:我是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()
使用此功能,绝对有效。
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')
您可以使用下面的SQL存储过程来计算包含任意数量变量的任何公式的结果:
我在2012年写了一个解决方案,它可以使用SQL SERVER评估任何类型的数学公式。该解决方案可以使用N个变量处理任何公式:
我被要求找到一种方法来评估由用户填写的公式给出的值。公式包含数学运算(加法,乘法,除法和减法)用于计算公式的参数存储在SQL服务器数据库中。
我自己找到的解决方案如下:
假设我有n个参数用于计算公式,这些参数中的每一个都存储在一个数据表的一行中。
在完整的脚本之后,我希望你发现它很有用,欢迎你向我询问。
该过程用作输入:
-公式
- 包含用于计算公式的值的表
如果存在(从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