【发布时间】:2021-03-13 06:07:00
【问题描述】:
我有 x 列,类型为 varchar2(26),并将值存储为:
0.00, 1, 2, 0.5, 0.25
我想将这些值作为数字数据复制到其他列,但出现错误:
ORA-01722:无效号码
我使用了以下代码:
ALTER TABLE tmp
ADD (x_1 NUMBER(3,2));
UPDATE tmp
SET x_1 = to_number(x, '9.99');
【问题讨论】:
我有 x 列,类型为 varchar2(26),并将值存储为:
0.00, 1, 2, 0.5, 0.25
我想将这些值作为数字数据复制到其他列,但出现错误:
ORA-01722:无效号码
我使用了以下代码:
ALTER TABLE tmp
ADD (x_1 NUMBER(3,2));
UPDATE tmp
SET x_1 = to_number(x, '9.99');
【问题讨论】:
你可以使用:
MERGE INTO tmp dst
USING (
WITH bounds ( x, rid, start_pos, end_pos ) AS (
SELECT x,
ROWID,
1,
INSTR( x, ',', 1 )
FROM tmp
UNION ALL
SELECT x,
rid,
end_pos + 1,
INSTR( x, ',', end_pos + 1 )
FROM bounds
WHERE end_pos > 0
)
SELECT x,
rid,
start_pos,
TO_NUMBER(
CASE end_pos
WHEN 0
THEN SUBSTR( x, start_pos )
ELSE SUBSTR( x, start_pos, end_pos - start_pos )
END
) AS value
FROM bounds
) src
ON ( src.rid = dst.ROWID AND src.start_pos = 1 )
WHEN MATCHED THEN
UPDATE SET x_1 = value
WHEN NOT MATCHED THEN
INSERT ( x, x_1 ) VALUES ( src.x, src.value );
其中,对于样本数据:
CREATE TABLE tmp (
x VARCHAR2(26)
);
INSERT INTO tmp ( x ) VALUES ( '0.00, 1, 2, 0.5, 0.25' );
ALTER TABLE tmp
ADD (x_1 NUMBER(3,2));
那么,合并之后:
SELECT * FROM tmp;
输出:
X | X_1 :-------------------- | --: 0.00, 1, 2, 0.5, 0.25 | 0 0.00, 1, 2, 0.5, 0.25 | 1 0.00, 1, 2, 0.5, 0.25 | 2 0.00, 1, 2, 0.5, 0.25 | .5 0.00, 1, 2, 0.5, 0.25 | .25
db小提琴here
【讨论】:
很明显,您的值不正确。您可以使用正则表达式仅更新有效值:
UPDATE tmp
SET x_1 = to_number(x, '9.99')
WHERE REGEXP_LIKE('^[0-9]?([.][0-9]{0,2})?$');
【讨论】:
根据您提供的数据,可以正常工作而不会出错。我假设您的数据比您显示的要多,并且“x”列中的一个值无法转换为数字。尝试这样的方法来识别这些问题值(我使用 -1 作为默认值,您需要选择一个未出现在表中的值):
select
x
, to_number(x DEFAULT -1 ON CONVERSION ERROR, '9.99') x_1
from tmp
where to_number(x DEFAULT -1 ON CONVERSION ERROR, '9.99') = -1;
更新
抱歉 - 以上示例仅适用于 12c。找到问题数据的最简单方法可能只是使用一些 SELECT 语句来观察它,但是如果您想使用编码解决方案,那么无论 Oracle 版本如何,这都可能有效(调整“return -1”值以确保它是不是实际出现在数据中的值):
CREATE or replace FUNCTION conv_to_num(x IN varchar)
RETURN NUMBER
IS conv_num NUMBER(3,2) := 0;
BEGIN
conv_num := to_number(x, '9.99');
return conv_num;
exception
WHEN OTHERS THEN
return -1;
END;
select
x
,conv_to_num(x) x_1
from tmp
;
【讨论】:
ON CONVERSION ERROR 在 Oracle 11 和 10 中工作吗?
我的问题是准确的。 x 列在下一行中有值,因此列看起来像
x
1 0.1
2 0.25
3 0.55
4 2
5 3
6 1.25
现在我需要相同的列,但数据类型为 NUMBER。
【讨论】: