SQL计算算数表达式的函数自定义(加减乘除)
一、整体思路:循环遍历表达式字符串,设置一个index从第一个字符开始检测当前数字是否可以和后面的数字进行运算,如果可以运算,将两个数挑出来运算,然后用运算的结果替换原来表达式中的这两个数和符号,计算后index又从1开始。如果不能运算则将当前index指向第二个数。如此循环直到表达式全部计算完毕。(简单的用一句话概括就是,找到优先级最高且靠前的两个子项先运算)
二、代码:
整体拆分成四个方法
SimpleCalculate匹配加减乘除char去计算两个数的结果
Create function [dbo].[SimpleCalculate](@num1 float,@num2 float,@sign char)
returns float
as begin
declare @result float
if @sign='+' begin
set @result=@num1+@num2
end
else if @sign='-' begin
set @result=@num1-@num2
end
else if @sign='*' begin
set @result=@num1*@num2
end
else if @sign='/' begin
set @result=@num1/@num2
end
return @result
end
GO
GetIsCal:比两个符号的优先级,第一个符号优先级高于第二个返回1(在下面介绍的[GetNumCondition]函数中会用到)
CREATE FUNCTION [dbo].[GetIsCal](@sign1 char, @sign2 char)
returns int
as begin
declare @isCal int
if (@sign1='+' or @sign1='-') and (@sign2='+' or @sign2='-') begin
set @isCal= 1
return @isCal
end
else begin
set @isCal= 0
end if (@sign1='*' or @sign1='/') and @sign2<>'(' begin
set @isCal= 1
return @isCal
end
else begin
set @isCal= 0
return @isCal
end
return @isCal end
GO
GetNumCondition:返回当前index指向的数字是否能进行运算,以及当前运算的数和运算符
CREATE FUNCTION [dbo].[GetNumCondition](@exp nvarchar(max), @index int)
returns @tmp table(numOne float,numTwo float, endindex int ,thissign char,nextsign char,Iscalc int,aa nvarchar(30))
as begin
insert @tmp(numOne) Values(null)
declare @isEnd int
declare @flag int
declare @end int
declare @thissign char
declare @nextsign char
set @end=0
set @end=@index+1
set @flag=1 --1表示 搜索第一个数字 2表示搜索第二个数字
set @isEnd=0
while @isEnd=0 begin
if @flag=1 begin --搜索第一个数
if ISNUMERIC(''+ SUBSTRING(@exp,@end,1))=1 begin --表示没有搜索到特殊符号
set @end= @end+1
continue;
end
else begin --表示搜索到特殊符号,第一个数搜索完毕
set @flag=2
update @tmp set numOne=SUBSTRING(@exp,@index,@end-@index)
update @tmp set thissign=SUBSTRING(@exp,@end,1)
set @index= @end+1
set @end= @index+1
if SUBSTRING(@exp,@index,1)='(' begin --第一个数的运算符后面是括号,不可运算,直接返回index值
update @tmp set Iscalc=0
update @tmp set endindex=@index+1
break
end
end
end set @thissign=(select top 1 thissign from @tmp) if @flag=2 begin
--if @thissign ='(' begin
--end
if ISNUMERIC( ''+SUBSTRING(@exp,@end,1))=1 and SUBSTRING(@exp,@end,1) is not null and SUBSTRING(@exp,@end,1)!='' begin --
set @end= @end+1
continue;
end
else begin --第二个数搜索完毕,开始更新返回值
if SUBSTRING(@exp,@end,1)=')' or SUBSTRING(@exp,@end,1)='' begin --两个数前后是括号,可以直接运算
update @tmp set Iscalc=1
update @tmp set endindex=@end-1
update @tmp set numTwo=SUBSTRING(@exp,@index,@end-@index)
break
end
set @isEnd=1
update @tmp set numTwo=SUBSTRING(@exp,@index,@end-@index)
update @tmp set nextsign=SUBSTRING(@exp,@end,1)
set @nextsign=SUBSTRING(@exp,@end,1)
update @tmp set Iscalc=dbo.GetIsCal(@thissign,@nextsign)
if dbo.GetIsCal(@thissign,@nextsign)=1 begin
update @tmp set endindex=@end-1
end
else begin
update @tmp set endindex=@index
end
end
end
end
return
end GO
主函数[GetExpressionResult]计算表达式
ALTER function [dbo].[GetExpressionResult](@exp nvarchar(max))
returns nvarchar(max) as
begin
declare @index int
set @index=1
while ISNUMERIC(@exp)=0
begin
declare @isCal int
declare @endindex int
select @isCal=Iscalc ,@endindex=endindex from dbo.GetNumCondition(@exp,@index)
if @isCal=1 begin
declare @numOne float
declare @numTwo float
declare @sign char
declare @cur_reslut float
select @numOne=cast(numOne as float),@numTwo=cast(numTwo as float),@sign=thissign from dbo.GetNumCondition(@exp,@index)
set @cur_reslut=dbo.SimpleCalculate(@numOne,@numTwo,@sign)
if SUBSTRING(@exp,@index-1,1)='(' and SUBSTRING(@exp,@endindex+1,1)=')' begin
set @exp=SUBSTRING(@exp,1,@index-2)+cast(@cur_reslut as nvarchar(20))+SUBSTRING(@exp,@endindex+2,len(@exp)-@endindex)
end
else begin
set @exp=SUBSTRING(@exp,1,@index-1)+cast(@cur_reslut as nvarchar(20))+SUBSTRING(@exp,@endindex+1,len(@exp)-@endindex)
end
set @index=1
end
else begin
set @index=@endindex
continue;
end
end
return @exp
end
GO
总结:业务需求中需要用到此方法,如若有错误和更多思路请不吝赐教, 另外有一篇文章的方法更加简洁:https://blog.csdn.net/scott_he/article/details/25835273
SQL计算算数表达式的函数自定义(加减乘除)的更多相关文章
- Oracle SQL Lesson (3) - 使用单行函数自定义输出
大小写转换函数LOWER('SQL Course') = sql courseUPPER('SQL Course') = SQL COURSEINITCAP('SQL Course') = Sql C ...
- EL表达式 EL函数 自定义el函数 《黑马程序员_超全面的JavaWeb视频教程vedio》
\JavaWeb视频教程_day12_自定义标签JSTL标签库,java web之设计模式\day12_avi\12.EL入门.avi; EL表达式 1. EL是JSP内置的表达式语言! * jsp2 ...
- SQL Fundamentals: Using Single-Row Functions to Customize Output使用单行函数自定义输出
SQL Fundamentals || Oracle SQL语言 DUAL is a public table that you can use to view results from functi ...
- 在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算)
原文:在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.
- Vue.js 第2章 钩子函数&自定义指令&过滤器&计算属性&侦听器
目标 钩子函数 自定义指令 自定义过滤器 计算属性 监听属性 局部自定义指令 为什么需要自定义指令 为了复用,为了代码的灵活 指令的分类:全局指令,局部指令 在vm外面创建的指令 通过Vue.dire ...
- Java工作流引擎节点接收人设置“按自定义SQL计算”系列讲解
关键字: 驰骋工作流程快速开发平台 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 开发者表单 拖拽式表单 工作流系统CCBPM节点访问规则接收人规则 适配数据库: o ...
- SQL Fundamentals || Single-Row Functions || 转换函数 Conversion function
SQL Fundamentals || Oracle SQL语言 SQL Fundamentals: Using Single-Row Functions to Customize Output使 ...
- SQL几种常用的函数
函数的种类: 算数函数(数值计算的函数) 字符串函数(字符串操作的函数) 日期函数(用来进行日期操作的函数) 转换函数(用来转换数据类型和值的函数) 聚合函数(用来进行数据聚合的函数) 算数函数(+- ...
- Sql总结之Sql--常用函数
控制流函数 IFNULL(expr1,expr2) 如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2.IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境 ...
随机推荐
- API参数如何验证?别纠结,拿去用就是
今天我们主要分享项目实战中,另一种常用的参数校验框架 Hibernate Validator,请准备好小板凳,我们的分享开始. 1. 是啥? 先抛一张图,锻炼一下你的观察力. 通过上图有没有发现,数据 ...
- 1037 Magic Coupon (25分)
The magic shop in Mars is offering some magic coupons. Each coupon has an integer N printed on it, m ...
- CF632(div.2)C. Eugene and an array
https://codeforces.ml/contest/1333/problem/C 大概题意是规定和为0的数组为不合格数组,询问给定数组中共有多少个合格子数组. 解题 子数组的数量 一个长度为 ...
- VAuditDemo代码审计
简介 先提一嘴,代码审计流程大概可以归结为:把握大局,定向功能,敏感函数参数回溯. 本文也是按照此思路进行,还在最后增加了漏洞修补方法. 本人平时打打CTF也有接触过代码审计,但都是零零散散的知识点. ...
- win10无法使用VMwareWorkstation的解决办法
最近(2019-10)国庆期间,微软更新了一次win10. 此次更新导致很多同学的Workstation pro不能用了. 主要的解决办法有一下几种: 卸载最新的系统更新包 在控制面板>> ...
- TP基础
一.目录结构 解压缩到web目录下面,可以看到初始的目录结构如下: www WEB部署目录(或者子目录)├─index.php 入口文件├─README.md README文件├─Applicatio ...
- python3(七)dict list
# dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. # dict内部存放的顺序和key放入的顺序是没有关系的 # 根据同学的名字 ...
- 01-启动jmeter目录功能
1.bin :存储了jmeter的可执行程序,如启动脚本.配置程序 docs: api扩展文档存放 lib: lib\ext 存储了jmeter的整合的功能(如.jar文件程序,和第三方 ...
- 006-循环结构(下)-C语言笔记
006-循环结构(下)-C语言笔记 学习目标 1.[掌握]do-while循环结构 2.[掌握]for循环结构 3.[掌握]嵌套循环 一.do-while循环结构 do-while语法: 1 2 ...
- 【Java】WrapperClass 包装类
什么是包装类? 写写我的想法 就是对于对象和基本类型的无法匹配和强转,基本类型在面向对象的实例类型中,反而成了个特殊的数据类型的存在 在一些特定的情况,我们希望通过对象的方式去处理数据,但是基本类型的 ...