I have an Oracle table (version 8i) which I need to migrate to sql server, one of the columns is a NUMBER datatype. In it, it has values like so:
--1331013400000000000000000000
--1331017903617177360300000000
--1331012863048235233700000000
among others
0.9574875526618150
2.51572327044025
The -- look like actual values stored in number column. I don't understand what the dash dash are for or what they mean, however, when I try to migrate data via ssma, i get "can't put string value into a float" so clearly sql server stumbles over this case, as I do.
I'm sure I can figure out a way to deal with this weird data, I'm just wondering what heck this means and what it's for, I Googled but surprisingly came out empty handed. Anyone have any clue?
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
Update:
It was a bug in a statistics calc library. Under certain conditions a function returning Doubles generated a NaN value when taking sqrt while calculation sdev. Oracle driver (oracle14.zip) used in prepared statement construction does not validate data, but sends and writes raw bytes, which is what ended up causing the corruption. Interestingly enough, MS SQL Server driver did not let me make a prepared statement and threw an exception when i tried to set a value that was a NaN in a prep statement. Posting this just as "fyi"...
It doesn't mean anything, and it isn't 'for' anything; your data is corrupt, I'm afraid. The
--
is an actual value from your table, but it isn't a number. Oracle's internal representation for numbers is covered in note 1031902.6 if you have access to that, or this explains it if you don't. If it was really a negative number then the last hexadecimal byte should be 66. Dumping the number it appears to be - with a single minus sign, not two, which is meaningless - gives:Creating invalid numbers in Oracle isn't straightforward (I suppose you wouldn't expect it to be), but this is a method I've used before. One of the clues, apart from the double minus sign and that they are all the same length, is that converting the dumped value back into a number doesn't give the same result:
This is from Oracle 9i, the closes I have now to an 8i database, so the results may vary a little.
Not being able to do
to_number(value)
is big clue too of course; there's an implicitto_char()
when you do that so it's trying to convert the text representation to a number, which explains the error. Theto_char()
value doesn't match what a simple select does either, interestingly. You'd see the same error if you did that with your data.Unless you know where the bad data came from and have the original still, you probably can't salvage these values. I think the best you can do is ignore it, or replace it with something that will migrate - if the field is nullable then
null
would be the safe option, otherwise I guess you'd have to pick a magic value.Identifying and modifying the affected rows can be done via a function; possibly something like:
With the same invalid value created earlier and one valid value:
Not ideal by any means, but at this point I think you're just salvaging what you can. You could delete the rows rather than updating them, or set the value to something else, it depends how you want to proceed.
You could try to get Oracle involved to see if they can figure out what happened and see if they have any tricks to get back to the original values - which seems unlikely - but I'm not sure you'd get a lot of support for such an old version of the database.
Of course, without knowing how and when the corruption was introduced (via a dodgy import perhaps, or via a buggy OCI program), you have to question the validity of all the other data, both in that column and elsewhere. In this case the corruption looks very uniform - all the invalid values seem to be constructed the same way - so you may be OK. Generally though, something that puts incorrect bytes into an internal value could fluke a wrong, but still valid, value. It could look about right, or it could be orders of magnitude out from the original expected value, and there's really no way to tell.