SQL挑战——如何高效生成编码

有这样一个需求:需要根据输入的编码(这个编码值来自于数据库的一个表)生成下一个编码,编码规则如下所示(我们暂且不关心这个逻辑是否合理,只关心如何实现):

   1: 最小值为A0000, 最大值为ZZZZZ
   2:编码A0000的下一个值为A0001, 编码A9999的下一个值为B0000, 编码AB999的下一个值为AC000,编码AC999的下一个值为AD000,依此规则内推。
   3:不用担心输入值为类似A09BC这样的值,应用程序会从表里面取编码的最大值。应用程序也会检查、控制输入参数,不用在数据库的函数(FUNCTION)里面做检查控制。
   4:不用担心输入值为ac908这种值(大小写问题),应用程序从表里获取编码的值(不接受用户输入)。所以这个的检查、控制也不用纳入数据库函数考虑范围。

看到同事用ASCII循环判断字符是否为数字,大量的逻辑处理,我觉得并不是如何高效而且有些弄复杂了,写了下面FUN_GEN_NEXT_CODE,用正则表达式获取数字部分,然后根据数字部分进行判断处理。 写完感觉也有点臃肿,因为要花大量的判断处理边界值(A9999 AZ999之类的边界值),但是暂时也没有更好的思路想法。 (ORACLE数据库实现)

CREATE OR REPLACE FUNCTION FUN_GEN_NEXT_CODE(MAX_DEMENSION_NO VARCHAR2)
RETURN VARCHAR2
IS
  CodeValue  NUMBER(5);
  CodeChar   VARCHAR(4);
  CharValue  VARCHAR2(5);
  ReturnCode VARCHAR2(5);
BEGIN
 
  IF LENGTH(MAX_DEMENSION_NO) >=6 OR LENGTH(MAX_DEMENSION_NO) < 5 THEN
    RETURN '';
  END IF;
  
  
  SELECT REGEXP_SUBSTR(MAX_DEMENSION_NO,'[[:digit:]]+') INTO CodeValue FROM DUAL;
  
  IF LENGTH(CodeValue)= 4 THEN
    IF CodeValue= 9999 THEN
       IF SUBSTR(MAX_DEMENSION_NO,1,1)='Z' THEN
          CharValue :='ZA';
          CodeChar := '000';
       ELSE
          CharValue :=CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,1,1)) +1);
          CodeChar := '0000';
       END IF;
    
    ELSE
       CharValue :=SUBSTR(MAX_DEMENSION_NO,0,1);
       CodeChar :=TRIM(TO_CHAR(CodeValue+1,'0000'));
    END IF;
 
     ReturnCode :=CharValue || CodeChar;
     
  ELSIF LENGTH(CodeValue)=3 THEN
    IF CodeValue= 999 THEN
       IF SUBSTR(MAX_DEMENSION_NO,1,2)='ZZ' THEN
          ReturnCode :='ZZA' || '00';
       ELSE
          IF SUBSTR(MAX_DEMENSION_NO,2,1) ='Z' THEN
              ReturnCode := CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,1,1)) +1) || '0000';
          ELSE
              ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,1) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,2,1)) +1) || '000';
          END IF;
       END IF;
    ELSE
       ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,1) || TRIM(TO_CHAR(CodeValue+1,'000'));
    END IF;
    
     
  ELSIF LENGTH(CodeValue)=2 THEN
    IF CodeValue= 99 THEN
       IF  SUBSTR(MAX_DEMENSION_NO,1,3) ='ZZZ' THEN
          ReturnCode :='ZZZA0';
       ELSE
          IF SUBSTR(MAX_DEMENSION_NO,3,1) ='Z' THEN
              ReturnCode := SUBSTR(MAX_DEMENSION_NO,1,1) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,2,1)) +1) + '000';
          ELSE 
              ReturnCode := SUBSTR(MAX_DEMENSION_NO,1,2) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,3,1)) +1) || '00';
          END IF;
       END IF;
    ELSE
       ReturnCode :=SUBSTR(MAX_DEMENSION_NO,1,3) + TRIM(TO_CHAR(CodeValue+1,'00'));
    END IF;
  ELSIF LENGTH(CodeValue)=1 THEN
     IF CodeValue= 9 THEN
        IF SUBSTR(MAX_DEMENSION_NO, 1,4) ='ZZZZ' THEN
            ReturnCode := 'ZZZZA';
        ELSE 
            ReturnCode := SUBSTR(MAX_DEMENSION_NO, 1,3) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,4,1)) +1) || '0';
        END IF;
    ELSE
            ReturnCode :=SUBSTR(MAX_DEMENSION_NO,0,4) || TRIM(TO_CHAR(CodeValue+1,'0'));
    END IF;
  ELSE 
    IF MAX_DEMENSION_NO='ZZZZZZ' THEN
       ReturnCode :='ZZZZZ';
    ELSE
       ReturnCode :=SUBSTR(MAX_DEMENSION_NO, 1,4) || CHR( ASCII(SUBSTR(MAX_DEMENSION_NO,5,1)) +1);
    END IF;
    
  END IF;
     RETURN ReturnCode;
   
EXCEPTION
   WHEN OTHERS
   THEN
      RETURN ('');
END FUN_GEN_NEXT_CODE;
时间: 2024-11-02 12:42:53

SQL挑战&mdash;&mdash;如何高效生成编码的相关文章

SQL挑战——如何高效生成编码

有这样一个需求:需要根据输入的编码(这个编码值来自于数据库的一个表)生成下一个编码,编码规则如下所示(我们暂且不关心这个逻辑是否合理,只关心如何实现):    1: 最小值为A0000, 最大值为ZZZZZ    2:编码A0000的下一个值为A0001, 编码A9999的下一个值为B0000, 编码AB999的下一个值为AC000,编码AC999的下一个值为AD000,依此规则内推.    3:不用担心输入值为类似A09BC这样的值,应用程序会从表里面取编码的最大值.应用程序也会检查.控制输入

MS SQL 挑战问题

群里面有位网友提出了这样一个SQL挑战问题(原话不是这样,为了说明问题,我略做调整些): 问题说明如下 有一条个销售报表TEST : 商品 金额 A 1400 B 800 C 790 ... ... 现在有这样一个需求(要写一个SQL取出如下数据):先按销售金额倒叙排序,然后从这个报表取出前N条记录,并且这N条记录的销售金额之和是总金额的80%(<= 80%), 80%将作为一个查询条件(有可能是20%,30%).他的想法是用嵌套函数 递归做法记录砍掉一半判断是否达到百分比 如果不足再取后半部分

淘宝数据库OceanBase SQL编译器部分 源码阅读--生成物理查询计划

SQL编译解析三部曲分为:构建语法树,制定逻辑计划,生成物理执行计划.前两个步骤请参见我的博客<<淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树>>和<<淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划>>.这篇博客主要研究第三步,生成物理查询计划. 一. 什么是物理查询计划 与之前的阅读方法一致,这篇博客的两个主要问题是what 和how.那么什么是物理查询计划?物理查询计划能够直接执行并返回数据结果数

淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划

淘宝数据库OceanBase SQL编译器部分 源码阅读--生成逻辑计划 SQL编译解析三部曲分为:构建语法树,生成逻辑计划,指定物理执行计划.第一步骤,在我的上一篇博客淘宝数据库OceanBase SQL编译器部分 源码阅读--解析SQL语法树里做了介绍,这篇博客主要研究第二步,生成逻辑计划. 一. 什么是逻辑计划? 我们已经知道,语法树就是一个树状的结构组织,每个节点代表一种类型的语法含义.如 update student set sex="M" where name ="

sql server根据表中数据生成insert语句

几个收藏的根据数据库生成Insert语句的存储过程[修正版] -- ======================================================--根据表中数据生成insert语句的存储过程--建立存储过程,执行spGenInsertSQL 表名--感谢playyuer----感谢szyicol-- ======================================================CREATE proc [dbo].[spGenInser

实现SQL Server 原生数据从XML生成JSON数据的实例代码

实现SQL Server 原生数据从XML生成JSON数据的实例代码 SQL Server 是关系数据库,查询结果通常都是数据集,但是在一些特殊需求下,我们需要XML数据,最近这些年,JSON作为WebAPI常用的交换数据格式,那么数据库如何生成JSON数据呢?今天就写了一个DEMO. 1.创建表及测试数据 SET NOCOUNT ON IF OBJECT_ID('STATS') IS NOT NULL DROP TABLE STATS IF OBJECT_ID('STATIONS') IS N

MS SQL巡检系列&amp;mdash;&amp;mdash;检查外键字段是否缺少索引

前言感想:一时兴起,突然想写一个关于MS SQL的巡检系列方面的文章,因为我觉得这方面的知识分享是有价值,也是非常有意义的.一方面,很多经验不足的人,对于巡检有点茫然,不知道要从哪些方面巡检,另外一方面,网上关于MS SQL巡检方面的资料好像也不是特别多.写这个系列只是一个分享,自己的初衷是一个知识梳理.总结提炼过程,有些知识和脚本也不是原创,文章很多地方融入了自己的一些想法和见解的,不足和肤浅之处肯定也非常多,抛砖引玉,也希望大家提意见和建议.补充,指正其中的不足之处.Stay Hungry

小心SQL SERVER 2014新特性&amp;mdash;&amp;mdash;基数评估引起一些性能问题

    在前阵子写的一篇博文"SQL SERVER 2014 下IF EXITS 居然引起执行计划变更的案例分享"里介绍了数据库从SQL SERVER 2005升级到 SQL SERVER 2014后,发现一个SQL出现性能问题,当时分析后发现执行计划变了,导致SQL出现了性能问题.但是没有彻底搞清楚为什么出现这种情况.当时看到Actual Number of Rows 与Estimated Number of Rows之间的偏差较大(统计信息是最新的),以为是优化器的Bug造成的.其

[翻译]&amp;mdash;&amp;mdash;SQL Server使用链接服务器的5个性能杀手

原文:[翻译]--SQL Server使用链接服务器的5个性能杀手  前言: 本文是对博客http://www.dbnewsfeed.com/2012/09/08/5-performance-killers-when-working-with-linked-servers/的翻译, 如有翻译不对或不好的地方,敬请指出,大家一起学习进步.尊重原创和翻译劳动成果,转载时请注明出处.谢谢!   当使用链接服务器(Linked Servers)时,最昂贵的代价就是网络带宽间大量数据的传输.在正确的服务器