如何在 Oracle SQL 中将 max(0.10)+1 设为 0.11
How to get max(0.10)+1 as 0.11 in Oracle SQL
我在 table 中的值为 0.0、0.1、0.2。我使用以下查询将 0.0、0.4、...0.10 填充到 table.
我正尝试在 table 中再添加 4 条记录,并期望值为 0.11、0.12、0.13、0.14。但是我的查询将它们全部填充为 0.10,因此重复。
以下是我的查询,请帮我解决这个问题。
--查询
SELECT nvl(MAX(substr(sequence_number, instr(sequence_number, '.') + 1, 1)) + 1, '0')
FROM TESTING_TBL;
---示例 table 创建脚本
CREATE TABLE TESTING_TBL (SEQUENCE_NUMBER VARCHAR2(30));
INSERT ALL INTO TESTING_TBL ( sequence_number ) VALUES ( '0.0' )
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.1')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.2')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.3')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.4')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.5')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.6')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.7')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.8')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.9')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.10')
SELECT '1' FROM dual;
谢谢!
您必须先将字符串分成两部分,然后将两部分转换为数字并应用 MAX
并增加 1。
这是一个示例查询
with tbl as (
select
SEQUENCE_NUMBER,
to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select SEQUENCE_NUMBER, NUM1, NUM2
from tbl
order by num1, num2;
提供数据为
SEQUENCE_NUMBER NUM1 NUM2
------------------------------ ---------- ----------
0.0 0 0
0.1 0 1
....
0.8 0 8
0.9 0 9
0.10 0 10
现在有了数字,您可以安全地找到 MAX 并加 1
with tbl as (
select
SEQUENCE_NUMBER,
to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select to_char(max(NUM1))||'.'||to_char(max(NUM2)+1) new_key
from tbl
产生预期结果
NEW_KEY
---------------------------------------------------------------------------------
0.11
请注意,如果这是最佳方法,您应该重新设计。作为更好更安全的选择,我会考虑存储两个 INT 列(类型安全!)并将文本表示仅定义为虚拟列:
CREATE TABLE TESTING_TBL2 (num1 int, num2 int);
alter table TESTING_TBL2 add SEQUENCE_NUMBER AS (to_char(num1)||'.'||to_char(num2)) VIRTUAL ;
添加测试数据
INSERT ALL INTO TESTING_TBL2 ( num1, num2 ) VALUES ( 0,0 )
-- ....
INTO TESTING_TBL2 (num1, num2) VALUES ( 0,9 )
INTO TESTING_TBL2 (num1, num2) VALUES ( 0,10)
SELECT '1' FROM dual;
现在这个简单的查询提供了新键
select max(num1) num1, max(num2)+1 num2 from TESTING_TBL2;
完整数据
select * from TESTING_TBL2;
NUM1 NUM2 SEQUENCE_NUMBER
---------- ---------- -------------------
0 0 0.0
0 9 0.9
0 10 0.10
还请记住,用于分配新密钥的 MAX + 1
算法在 单用户 环境中效果最佳。
抛开关于这是否是一个好主意的各种合理评论......
眼前的问题是您将子字符串的长度限制为 1:
SELECT nvl(MAX(substr(sequence_number, instr(sequence_number, '.') + 1 , 1)) + 1, '0')
当小数点后只有一位时,这可以正常工作,所以你可以插入 0.10。那时,substr returns “1”,而不是您可能想要的“10”。我的猜测是这会导致您再次尝试插入“0.2”,从而导致违反唯一性。
如果它适用于您的所有输入,您应该只删除该长度参数。但是如果你必须处理更复杂的字符串,比如'0.10.3',你可能需要使用正则表达式来进行解析。或者,正如其他人所建议的那样,将此字符串的子组件存储为单独的数值,并使用虚拟列或在插入到最终 table.
期间将它们连接起来
感谢大家花时间解决我的问题。感谢您的所有努力。
我将小数点前后分开,并使用下面的查询来增加小数点后的数字。它解决了我的问题。
SELECT NVL(MAX(SUBSTR(sequence_number, 3)+1),'0')
FROM TESTING_TBL;
我在 table 中的值为 0.0、0.1、0.2。我使用以下查询将 0.0、0.4、...0.10 填充到 table.
我正尝试在 table 中再添加 4 条记录,并期望值为 0.11、0.12、0.13、0.14。但是我的查询将它们全部填充为 0.10,因此重复。
以下是我的查询,请帮我解决这个问题。
--查询
SELECT nvl(MAX(substr(sequence_number, instr(sequence_number, '.') + 1, 1)) + 1, '0')
FROM TESTING_TBL;
---示例 table 创建脚本
CREATE TABLE TESTING_TBL (SEQUENCE_NUMBER VARCHAR2(30));
INSERT ALL INTO TESTING_TBL ( sequence_number ) VALUES ( '0.0' )
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.1')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.2')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.3')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.4')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.5')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.6')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.7')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.8')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.9')
INTO TESTING_TBL (SEQUENCE_NUMBER) VALUES ('0.10')
SELECT '1' FROM dual;
谢谢!
您必须先将字符串分成两部分,然后将两部分转换为数字并应用 MAX
并增加 1。
这是一个示例查询
with tbl as (
select
SEQUENCE_NUMBER,
to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select SEQUENCE_NUMBER, NUM1, NUM2
from tbl
order by num1, num2;
提供数据为
SEQUENCE_NUMBER NUM1 NUM2
------------------------------ ---------- ----------
0.0 0 0
0.1 0 1
....
0.8 0 8
0.9 0 9
0.10 0 10
现在有了数字,您可以安全地找到 MAX 并加 1
with tbl as (
select
SEQUENCE_NUMBER,
to_number(substr(SEQUENCE_NUMBER,1,instr(SEQUENCE_NUMBER,'.')-1)) num1,
to_number(substr(SEQUENCE_NUMBER,instr(SEQUENCE_NUMBER,'.')+1)) num2
from TESTING_TBL)
select to_char(max(NUM1))||'.'||to_char(max(NUM2)+1) new_key
from tbl
产生预期结果
NEW_KEY
---------------------------------------------------------------------------------
0.11
请注意,如果这是最佳方法,您应该重新设计。作为更好更安全的选择,我会考虑存储两个 INT 列(类型安全!)并将文本表示仅定义为虚拟列:
CREATE TABLE TESTING_TBL2 (num1 int, num2 int);
alter table TESTING_TBL2 add SEQUENCE_NUMBER AS (to_char(num1)||'.'||to_char(num2)) VIRTUAL ;
添加测试数据
INSERT ALL INTO TESTING_TBL2 ( num1, num2 ) VALUES ( 0,0 )
-- ....
INTO TESTING_TBL2 (num1, num2) VALUES ( 0,9 )
INTO TESTING_TBL2 (num1, num2) VALUES ( 0,10)
SELECT '1' FROM dual;
现在这个简单的查询提供了新键
select max(num1) num1, max(num2)+1 num2 from TESTING_TBL2;
完整数据
select * from TESTING_TBL2;
NUM1 NUM2 SEQUENCE_NUMBER
---------- ---------- -------------------
0 0 0.0
0 9 0.9
0 10 0.10
还请记住,用于分配新密钥的 MAX + 1
算法在 单用户 环境中效果最佳。
抛开关于这是否是一个好主意的各种合理评论......
眼前的问题是您将子字符串的长度限制为 1:
SELECT nvl(MAX(substr(sequence_number, instr(sequence_number, '.') + 1 , 1)) + 1, '0')
当小数点后只有一位时,这可以正常工作,所以你可以插入 0.10。那时,substr returns “1”,而不是您可能想要的“10”。我的猜测是这会导致您再次尝试插入“0.2”,从而导致违反唯一性。
如果它适用于您的所有输入,您应该只删除该长度参数。但是如果你必须处理更复杂的字符串,比如'0.10.3',你可能需要使用正则表达式来进行解析。或者,正如其他人所建议的那样,将此字符串的子组件存储为单独的数值,并使用虚拟列或在插入到最终 table.
期间将它们连接起来感谢大家花时间解决我的问题。感谢您的所有努力。
我将小数点前后分开,并使用下面的查询来增加小数点后的数字。它解决了我的问题。
SELECT NVL(MAX(SUBSTR(sequence_number, 3)+1),'0')
FROM TESTING_TBL;