一、整体思路:循环遍历表达式字符串,设置一个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计算算数表达式的函数自定义(加减乘除)的更多相关文章

  1. Oracle SQL Lesson (3) - 使用单行函数自定义输出

    大小写转换函数LOWER('SQL Course') = sql courseUPPER('SQL Course') = SQL COURSEINITCAP('SQL Course') = Sql C ...

  2. EL表达式 EL函数 自定义el函数 《黑马程序员_超全面的JavaWeb视频教程vedio》

    \JavaWeb视频教程_day12_自定义标签JSTL标签库,java web之设计模式\day12_avi\12.EL入门.avi; EL表达式 1. EL是JSP内置的表达式语言! * jsp2 ...

  3. 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 ...

  4. 在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算)

    原文:在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.

  5. Vue.js 第2章 钩子函数&自定义指令&过滤器&计算属性&侦听器

    目标 钩子函数 自定义指令 自定义过滤器 计算属性 监听属性 局部自定义指令 为什么需要自定义指令 为了复用,为了代码的灵活 指令的分类:全局指令,局部指令 在vm外面创建的指令 通过Vue.dire ...

  6. Java工作流引擎节点接收人设置“按自定义SQL计算”系列讲解

    关键字: 驰骋工作流程快速开发平台 工作流程管理系统 工作流引擎 asp.net工作流引擎 java工作流引擎. 开发者表单  拖拽式表单 工作流系统CCBPM节点访问规则接收人规则 适配数据库: o ...

  7. SQL Fundamentals || Single-Row Functions || 转换函数 Conversion function

    SQL Fundamentals || Oracle SQL语言   SQL Fundamentals: Using Single-Row Functions to Customize Output使 ...

  8. SQL几种常用的函数

    函数的种类: 算数函数(数值计算的函数) 字符串函数(字符串操作的函数) 日期函数(用来进行日期操作的函数) 转换函数(用来转换数据类型和值的函数) 聚合函数(用来进行数据聚合的函数) 算数函数(+- ...

  9. Sql总结之Sql--常用函数

    控制流函数 IFNULL(expr1,expr2) 如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2.IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境 ...

随机推荐

  1. API参数如何验证?别纠结,拿去用就是

    今天我们主要分享项目实战中,另一种常用的参数校验框架 Hibernate Validator,请准备好小板凳,我们的分享开始. 1. 是啥? 先抛一张图,锻炼一下你的观察力. 通过上图有没有发现,数据 ...

  2. 1037 Magic Coupon (25分)

    The magic shop in Mars is offering some magic coupons. Each coupon has an integer N printed on it, m ...

  3. CF632(div.2)C. Eugene and an array

    https://codeforces.ml/contest/1333/problem/C 大概题意是规定和为0的数组为不合格数组,询问给定数组中共有多少个合格子数组. 解题 子数组的数量 一个长度为 ...

  4. VAuditDemo代码审计

    简介 先提一嘴,代码审计流程大概可以归结为:把握大局,定向功能,敏感函数参数回溯. 本文也是按照此思路进行,还在最后增加了漏洞修补方法. 本人平时打打CTF也有接触过代码审计,但都是零零散散的知识点. ...

  5. win10无法使用VMwareWorkstation的解决办法

    最近(2019-10)国庆期间,微软更新了一次win10. 此次更新导致很多同学的Workstation pro不能用了. 主要的解决办法有一下几种: 卸载最新的系统更新包 在控制面板>> ...

  6. TP基础

    一.目录结构 解压缩到web目录下面,可以看到初始的目录结构如下: www WEB部署目录(或者子目录)├─index.php 入口文件├─README.md README文件├─Applicatio ...

  7. python3(七)dict list

    # dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. # dict内部存放的顺序和key放入的顺序是没有关系的 # 根据同学的名字 ...

  8. 01-启动jmeter目录功能

    1.bin :存储了jmeter的可执行程序,如启动脚本.配置程序 docs:    api扩展文档存放 lib:   lib\ext   存储了jmeter的整合的功能(如.jar文件程序,和第三方 ...

  9. 006-循环结构(下)-C语言笔记

    006-循环结构(下)-C语言笔记 学习目标 1.[掌握]do-while循环结构 2.[掌握]for循环结构 3.[掌握]嵌套循环 一.do-while循环结构 do-while语法:   1 2 ...

  10. 【Java】WrapperClass 包装类

    什么是包装类? 写写我的想法 就是对于对象和基本类型的无法匹配和强转,基本类型在面向对象的实例类型中,反而成了个特殊的数据类型的存在 在一些特定的情况,我们希望通过对象的方式去处理数据,但是基本类型的 ...