Обычно ошибка возникает при загрузки данных из текстового файла с помощью Oracle Sqlloader. Ошибка связана с тем, что в России разделитель целой и дробной часть запятая, а в США и Европе – точка.
Если попытаться загрузить в базу некорректно отформатированные данные, то Oracle их не поймет. Выйти из этого положения можно несколькими способами. Некоторые проще, некоторые сложне. Давайте рассмотрим их. Вначале простые, к концу более сложные и, возможно, чреватые проблемами.
1. Зайти в файл и заменить все точки на запятые. Например
1|New York|NY|7322564|1|2001|8307|-73.943849000|40.669800000|
заменяем на
1|New York|NY|7322564|1|2001|8307|-73,943849000|40,669800000|
Тут всеп просто. Никаких подводных камней, кроме того, что точки могут встречаться не только в числах и это надо отслеживать, иначе испортите данные.
Например в Linux это легко сделать с помощью sed (для Windows можно взять отсюда или использовать, скажем, perl). Команда не создает резервной копии.
sed -i 's/\./,/g' filename.txt
2. В локальном файле при загрузке данных установить соответствующие параметры NLS.
Например, если загрузка осуществляется следующим скриптом батником:
sqlldr scott/tiger@orcl control=us_cities\us_cities.ctl data=us_cities\us_cities.dat
то ошибки можно избежать с помощью выполнения предварительно в bat-файле вот такой команды:
set nls_lang=american_america.CL8MSWIN1251
sqlldr scott/tiger@orcl control=us_cities\us_cities.ctl data=us_cities\us_cities.dat
Я считаю этот вариант наиболее предпочтительным.
3. Если это Windows, то можно изменить глобальные настройки NLS. Сделать это можно в реестре в веточке
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraClient10g_home1\NLS_LANG
Нужно будет вместо значения RUSSIAN_RUSSIA.CL8MSWIN1251 прописать AMERICAN_AMERICA.CL8MSWIN1251.
Это решение может очень сильно повлиять на систему в целом. Действие этого параметра может повлечь неработоспособность другого приложения.
3 комментария:
очевидно, что sed это не только *nix, это просто "UNIX-way" - достаточно на google написать sed.exe
Ну и приведённая выше строчка не учитывает точки в тексте.
Я позволю себе небольшое добавление:
sed -i 's/\([0-9]\+\)\.\([0-9]\+\)/\1,\2/g'
То есть перед точкой должна быть цифра [0-9], одна или больше (+) и после точки - тоже. Ну и заменить на запятую, используя найденные в скобках паттерны \1 и \2. Тут, правда, не рассматривается вариант со знаком (+-), ведущими после него пробелами и отсутствием ведущего нуля (- .123), но это можно прогуглировать
Спасибо, Стас!
Каюсь :) Поленился подольше погуглить насчет паттерна, который бы учитывал текст. А придумать самостоятельно навскидку - не такой я глубокий специалист в линуксе.
Очень полезная маска.
уф... Стас, ты меня спас. Спасибо огромное.
Отправить комментарий