Дефисы Oracle 2 в числовом столбце?

У меня есть таблица Oracle (версия 8i), которую мне нужно перенести на сервер sql, один из столбцов имеет тип данных NUMBER. В нем он имеет такие значения:

--1331013400000000000000000000
--1331017903617177360300000000
--1331012863048235233700000000

среди прочего

0.9574875526618150
2.51572327044025

-- выглядят как фактические значения, хранящиеся в числовом столбце. Я не понимаю, для чего нужен тире тире или что они означают, однако, когда я пытаюсь перенести данные через ssma, я получаю «не могу поместить строковое значение в число с плавающей запятой», поэтому ясно, что сервер sql спотыкается об этот случай, поскольку Я делаю.

Я уверен, что смогу найти способ справиться с этими странными данными, мне просто интересно, что, черт возьми, это значит и для чего это нужно, я погуглил, но на удивление вышел с пустыми руками. Кто-нибудь знает?

дамп 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, генерировала значение NaN при получении sqrt при вычислении sdev. Драйвер Oracle (oracle14.zip), используемый в построении подготовленного оператора, не проверяет данные, а отправляет и записывает необработанные байты, что и привело к повреждению. Интересно, что драйвер MS SQL Server не позволил мне сделать подготовленный оператор и выдал исключение, когда я попытался установить значение, которое было NaN в операторе подготовки. Опубликовать это просто как "fyi"...


person niken    schedule 15.11.2013    source источник
comment
Какой инструмент/команду вы использовали для получения этого вывода?   -  person Arturo Hernandez    schedule 15.11.2013
comment
Все мы знаем, что не существует чисел, начинающихся с --. Таким образом, эти значения не могут быть сохранены в поле NUMBER. Это всего лишь демонстрация, как предполагает Артуро Эрнандес.   -  person Thorsten Kettner    schedule 15.11.2013
comment
Помощник по миграции сервера sql споткнулся на поле, помеченном как число в оракуле, которое может быть преобразовано в число с плавающей запятой на сервере sql, с ошибкой msg не может поместить строку в число с плавающей запятой, когда я запрашиваю таблицу, я вижу результат. Я также сделал дамп структуры и данных sql, так что не для отображения. странная часть, когда я пытаюсь повторно вставить строку с аналогичным значением, я получаю [Err] ORA-01722: неверный номер   -  person niken    schedule 15.11.2013
comment
Если это действительно числовой столбец, то данные выглядят поврежденными — как они были вставлены? Можете ли вы добавить внутреннее представление из dump(<column>, 1016) для этих строк?   -  person Alex Poole    schedule 15.11.2013


Ответы (1)


Это ничего не значит и ни для чего; ваши данные повреждены, я боюсь. -- — это фактическое значение из вашей таблицы, но это не число. Внутреннее представление Oracle для чисел описано в примечании 1031902.6, если у вас есть к нему доступ, или это объясняет, если у вас нет . Если бы это было действительно отрицательное число, то последний шестнадцатеричный байт должен быть 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, тогда 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), вы должны подвергнуть сомнению достоверность всех других данных, как в этом столбце, так и в других местах. В этом случае повреждение выглядит очень однородным — все недопустимые значения кажутся построенными одинаково — так что вы можете быть в порядке. Однако, как правило, что-то, что помещает неправильные байты во внутреннее значение, может привести к неправильному, но все же допустимому значению. Оно может выглядеть примерно так, а может отличаться от исходного ожидаемого значения на несколько порядков, и на самом деле нет никакого способа сказать.

person Alex Poole    schedule 15.11.2013
comment
Большое спасибо за это, действительно полезно. Я поиграл с вашей функцией, используя convert_raw_value для вставки чисел, кажется, что значения, начинающиеся с «32ea», вызовут повреждение. Достаточно интересно, что ea00 дает огромное число -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 - person niken; 18.11.2013