我在Oracle 10g数据库上运行。 该表有一个CODE列,它是主键,是一个varchar。 字段始终采用格式“xx xxx xx”,例如“20 965 04”,第一个和第二个是不相关的数字,最后一个部分是连续数字。
我要做的是,执行一个INSERT,其中前两个部分的密钥保持不变,最后一个部分比这些特定的第一部分的最高连续数字多一个。
所以,我开始玩一个小小的,我的第一个方法是:
SUBSTR('20 031 03', 0, 7)||(TO_CHAR(TO_NUMBER(
SUBSTR(
(SELECT MAX(CODE )
FROM table tmk
WHERE tmk.CODE LIKE SUBSTR('20 031 03', 0, 6)||'%')
, 8, 9) ) + 1
))
这种方法已经不是很漂亮了,但在我看来还行。 但后来我意识到,当连续数字低于10时,在TO_NUMBER和TO_CHAR之后,它是cource,例如5而不是05。 所以,如果我有“20 965 04”,我得到的是“20 965 5”,但我需要“20 965 05”!
所以,我能想到的唯一方法是在增加数字后检查字符串长度的case语句,如果是neccecary则添加0:
SELECT
CASE (LENGTH(TO_CHAR(TO_NUMBER( SUBSTR(
(SELECT MAX(CODE)
FROM table tmk
WHERE tmk.CODE LIKE SUBSTR('20 031 03', 0, 6)||'%')
, 8, 9) ) + 1
)))
WHEN 1 THEN
SUBSTR('20 031 03', 0, 7)||'0'||(TO_CHAR(TO_NUMBER(
SUBSTR(
(SELECT MAX(CODE)
FROM table tmk
WHERE tmk.CODE LIKE SUBSTR('20 031 03', 0, 6)||'%')
, 8, 9) ) + 1
))
ELSE
SUBSTR('20 031 03', 0, 7)||(TO_CHAR(TO_NUMBER(
SUBSTR(
(SELECT MAX(CODE)
FROM table tmk
WHERE tmk.CODE LIKE SUBSTR('20 031 03', 0, 6)||'%')
, 8, 9) ) + 1
))
END
FROM dual;
所以这很有效,但它就像我见过的最丑陋的SQL。但由于我目前不知何故坚持下去,有没有人有更好更短的方法来做同样的事情?
答案 0 :(得分:1)
查看LPAD
功能。
例如,SELECT LPAD(1,2,'0') FROM DUAL
将返回01
。
答案 1 :(得分:0)
TO_CHAR函数有一个可以使用的格式参数:
SUBSTR('20 031 03', 1, 7) ||
TO_CHAR(
TO_NUMBER(
SUBSTR(
(SELECT MAX(CODE) FROM table tmk WHERE tmk.CODE LIKE SUBSTR('20 031 03', 1, 6) || '%')
, 8, 2) + 1
)
, 'FM00')
我稍微改变了你的SUBSTR参数。索引从1开始。您想要最后两位数。