我有一个Oracle表(版本8i),我需要迁移到sql server,其中一列是NUMBER数据类型。在其中,它具有如下值:
--1331013400000000000000000000
--1331017903617177360300000000
--1331012863048235233700000000
等等
0.9574875526618150
2.51572327044025
- 看起来像存储在数字列中的实际值。我不明白破折号是什么或它们意味着什么,但是,当我尝试通过ssma迁移数据时,我得到“无法将字符串值放入浮点数”,所以很明显sql server在这种情况下会遇到麻烦,因为我做。
我确信我可以找到一种方法来处理这些奇怪的数据,我只是想知道这意味着什么,它是什么,我用Google搜索,但令人惊讶的是空手而归。任何人都有任何线索?
dump 1016:
0.2722718362012630 Typ=2 Len=9: c0,1c,17,48,54,3f,2,1b,1f
--1331013400000000000000000000 Typ=2 Len=4: 32,ea,0,43
0.50761421319797 Typ=2 Len=8: c0,33,4d,f,16,20,62,62
1 Typ=2 Len=2: c1,2
0.9574875526618150 Typ=2 Len=9: c0,60,4b,58,38,1b,3e,52,33
1.11894371713103 Typ=2 Len=9: c1,2,c,5a,2c,48,48,20,4
2.51572327044025 Typ=2 Len=9: c1,3,34,3a,18,1c,5,29,1a
0.0537258905066351 Typ=2 Len=9: c0,6,26,1a,5a,6,7,40,34
0.1851303317535540 Typ=2 Len=9: c0,13,34,1f,22,12,36,38,29
0.0000000000000000000000000000306386 Typ=2 Len=4: b2,1f,40,57
1.6164 Typ=2 Len=4: c1,2,3e,41
0.1289839930864580 Typ=2 Len=9: c0,d,5a,54,64,1f,57,2e,51
0.004721435316336170 Typ=2 Len=9: bf,30,16,2c,36,11,22,3e,47
--1331017903617177360300000000 Typ=2 Len=10: 32,ea,0,16,62,28,1e,18,41,62
--1331012863048235233700000000 Typ=2 Len=10: 32,ea,0,49,26,61,13,42,4e,40
--1331010715609612880500000000 Typ=2 Len=10: 32,ea,0,5e,56,29,5,59,d,60
0.0778391842453491 Typ=2 Len=9: c0,8,4f,28,13,2b,2e,23,5c
--1331010187793684447000000000 Typ=2 Len=10: 32,ea,0,64,e,16,41,11,39,1f
0.8296 Typ=2 Len=3: c0,53,61
--1331015225486314961400000000 Typ=2 Len=10: 32,ea,0,31,4c,35,26,57,5,57
--1331016035469906437500000000 Typ=2 Len=10: 32,ea,0,29,42,37,2,5f,3a,1a
0.3301637612255680 Typ=2 Len=9: c0,22,2,40,4d,d,1a,39,51
0.2666453350398630 Typ=2 Len=9: c0,1b,43,2e,22,33,28,57,1f
0.1581527755812110 Typ=2 Len=9: c0,10,52,35,4e,38,52,16,b
0.8089305937550560 Typ=2 Len=9: c0,51,5a,1f,3c,26,38,6,3d
--1331015006297067350000000000 Typ=2 Len=9: 32,ea,0,33,5f,48,1f,22,42
0.3745318352059930 Typ=2 Len=9: c0,26,2e,20,54,35,6,64,1f
--1331017625157985988000000000 Typ=2 Len=10: 32,ea,0,19,4c,56,16,10,3,15
更新
这是统计计算库中的一个错误。在某些条件下,返回Doubles的函数在计算sdev时获取sqrt时会生成NaN值。在预准备语句构造中使用的Oracle驱动程序(oracle14.zip)不验证数据,而是发送和写入原始字节,这最终导致损坏。有趣的是,当我试图在准备语句中设置一个NaN值时,MS SQL Server驱动程序不允许我制作一个准备好的语句并引发异常。发布这个就像“fyi”......
答案 0 :(得分:7)
它没有任何意义,它不是'为'任何东西;我担心你的数据是腐败的。 --
是表中的实际值,但它不是数字。如果您可以访问Oracle,则会在注释1031902.6中介绍Oracle的内部数字表示,或this explains it if you don't。如果它真的是一个负数,那么最后一个十六进制字节应该是66.倾倒它看起来的数字 - 用一个减号,而不是两个,这是没有意义的 - 给出:
select dump(-1331013400000000000000000000, 1016) from dual;
DUMP(-1331013400000000000000000000,1016)
----------------------------------------
Typ=2 Len=6: 31,58,46,64,43,66
在Oracle中创建无效数字并不简单(我想您不会期望它),但这是我之前使用过的方法。其中一条线索,除了双减号以及它们都是相同的长度之外,将转储后的值转换回数字并不会产生相同的结果:
create table t42(value number);
declare
n number;
begin
dbms_stats.convert_raw_value('32ea004366', n);
insert into t42 (value) values (n);
end;
/
select value from t42;
VALUE
--------------------------------------
-<3:13400000000000000000000
这是来自Oracle 9i,我现在关闭到8i数据库,所以结果可能会有所不同。
无法做to_number(value)
当然也是一个很大的线索;当你这样做时有一个隐含的to_char()
,所以它试图将文本表示转换为数字,这解释了错误。有趣的是,to_char()
值与简单选择的值不匹配。如果您使用数据执行此操作,则会看到相同的错误。
select to_number(value) from t42;
select to_number(value) from t42
*
ERROR at line 1:
ORA-01722: invalid number
select to_char(value) from t42;
TO_CHAR(VALUE)
----------------------------------------
-`003400000000000000000000
除非您知道坏数据的来源并保留原始数据,否则您可能无法挽救这些值。我认为你能做的最好就是忽略它,或者用可以迁移的东西代替它 - 如果字段可以为空,那么null
将是安全的选择,否则我猜你必须选择一个神奇的值。
识别和修改受影响的行可以通过函数完成;可能是这样的:
create or replace function null_bad_number(value number)
return number deterministic as
tmp_value number;
invalid_number exception;
pragma exception_init(invalid_number, -1722);
begin
select to_number(value) into tmp_value from dual;
return value;
exception
when invalid_number then
return null;
end;
/
使用前面创建的相同无效值和一个有效值:
insert into t42 (value) values (0.9574875526618150);
select * from t42;
VALUE
----------
-`.003E+24
.957487553
update t42 set value = null
where value is not null
and null_bad_number(value) is null;
1 row updated.
select * from t42;
VALUE
----------
.957487553
无论如何都不理想,但在这一点上,我认为你只是在挽救你所能做到的。您可以删除行而不是更新它们,或者将值设置为其他值,这取决于您希望如何继续。
你可以尝试让Oracle参与进来,看看他们是否能弄清楚发生了什么,看看他们是否有任何技巧可以回到原来的价值 - 这似乎不太可能 - 但我不确定你会得到很多支持这种旧版本的数据库。
当然,如果不知道如何以及何时引入了腐败(可能是通过狡猾的导入,或通过错误的OCI程序),您必须质疑该列和其他地方的所有其他数据的有效性。在这种情况下,损坏看起来非常统一 - 所有无效值似乎都以相同的方式构造 - 所以你可能没问题。一般来说,将不正确的字节放入内部值的东西可能会导致错误但仍然有效的值。它可能看起来是正确的,或者可能是原始预期值的数量级,并且真的没有办法说出来。