Writing a Version Number Function in PL/SQL

十年热恋 提交于 2021-01-29 13:23:06

问题


I want to write a function that will give me the next version number for a table. The table stores the existing version on each record. For example, I have the cat table

cats

seqid    1
name     Mr Smith
version number  1.2b.3.4

How can I write a program that will be able to increment these values based on various conditions?

This is my first attempt

if v_username is not null
then v_new_nbr = substr(v_cur_nbr, 1,7)||to_number(substr(v_cur_nbr, 8,1))+1

should be 1.2b.3.5


回答1:


substr(v_cur_nbr, 1,7)||to_number(substr(v_cur_nbr, 8,1))+1

This hurls ORA-01722: invalid number. The reason is a subtle one. It seems Oracle applies the concatenation operator before the additions, so effectively you're adding one to the string '1.2b.3.4'.

One solution is using a TO_CHAR function to bracket the addition with the second substring before concatenating the result with the first substring:

substr(v_cur_nbr, 1,7) || to_char(to_number(substr(v_cur_nbr, 8,1))+1)

Working demo on db<>fiddle.


Incidentally, a key like this is a bad piece of data modelling. Smart keys are dumb. They always lead to horrible SQL (as you're finding) and risk data corruption. A proper model would have separate columns for each element of the version number. We can use virtual columns to concatenate the version number for display circumstances.

create table cats(
seqid    number
,name     varchar2(32)
,major_ver_no1 number
,major_ver_no2 number
,variant varchar2(1)
,minor_ver_no1 number
,minor_ver_no2 number
,v_cur_nbr  varchar2(16) generated always as (to_char(major_ver_no1,'FM9') ||'.'||
                                              to_char(major_ver_no2,'FM9')  ||'.'||
                                              variant  ||'.'||
                                              to_char(minor_ver_no1,'FM9')  ||'.'||
                                              to_char(minor_ver_no2,'FM9') ) );

So the set-up is a bit of a nause but incrementing the version numbers is a piece of cake.

update cats
set major_ver_no1 = major_ver_no1 +1 
    , major_ver_no2 = 0
    , variant = 'a';

There's a db<>fiddle for that too.




回答2:


Try searching mask for TO_NUMBER to be able to get the decimal number, this small example might help:

CREATE TABLE tmp_table (version varchar2(100));
INSERT INTO tmp_table(version) VALUES ('1.2b.3.4');
DECLARE
    mainVersion NUMBER;
    subVersion  NUMBER;
    currentVersion VARCHAR2(100);
BEGIN
    SELECT version INTO currentVersion FROM tmp_table;
    mainVersion := TO_NUMBER(SUBSTR(currentVersion,1,3),'9.9') + 0.1;
    subVersion  := TO_NUMBER(SUBSTR(currentVersion,6,3),'9.9') + 1.1;
    UPDATE tmp_table SET version = (mainVersion||'b.'||subVersion);
END;


来源:https://stackoverflow.com/questions/60042791/writing-a-version-number-function-in-pl-sql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!