SQLException: извлеченное значение столбца было усечено при выполнении while (rs.getNext ()) - PullRequest
4 голосов
/ 19 января 2009

У меня есть программа, которая извлекает большой набор данных из Oracle 10g (10.2.0.3), используя довольно простой запрос. Вы могли бы почти назвать запрос / логику своего рода «экспортом», так как он выбирает столбцы из таблицы с минимальным предложением where (то есть возвращает большинство, если не все строки).

Код [Java] - это образец, который мы все видели:

Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
    con = getConnection(Person);
    pstmt = con.prepareStatement(
            "SELECT ID, FIRST_NAME, LAST_NAME, ... FROM PERSON WHERE ...");
    rs = pstmt.executeQuery();
    while (rs.next()) {
        // write the data to a file
    }
}
finally {
    if (rs != null) try { rs.close(); } catch (Exception e) { }
    if (pstmt != null) try {pstmt.close(); } catch (Exception e) { }
    if (con != null) try { con.close() ; } catch (Exception e) { }
}

getConnection - это мой собственный метод, который возвращает объект Connection в базу данных Oracle, которая используется для таблицы «PERSON». Это похоже на обычный вопрос программирования, но я писал такой код много раз и никогда не сталкивался с такой проблемой.

Я получаю исключение java.sql.SQLException: ORA-01406: извлеченное значение столбца было усечено в строке while (rs.next ()). В документации Oracle, которую я прочитал, говорится, что «операция FETCH была вынуждена усечь строку символов». Он предлагает использовать больший буфер столбцов для хранения самого большого столбца. Но это не имеет смысла. В части приведенного выше кода, который комментируется как «записать данные в файл», я просто пишу каждый столбец как rs.getBigDecimal («ID»), rs.getString («FIRST_NAME» и т. Д.) Воспроизведите область с помощью пустого цикла while, который ничего не делает с ResultSet, то есть, просто перебирая ResultSet, выдается исключение SQLException.

Размер возвращаемого набора данных должен составлять приблизительно 1 миллион строк. Я получаю исключение после примерно 600 000 строк / итераций в цикле. Есть идеи?

Ответы [ 4 ]

1 голос
/ 19 января 2009

ЛИЦО - это таблица или представление?

В какой-то момент, под прикрытием, Java должна определить длину данных для данных. И я думаю, что он делает это неправильно. Во-первых, удалите столбцы один за другим, чтобы вы могли определить, какой столбец работает неправильно. Затем, возможно, просмотрите данные порциями (например, 1-100000, 100001-200000 и т. Д.), Чтобы найти порцию, которая вызывает ошибку. Затем сузьте куски (100000-150000 и т. Д.), Пока не найдете одну строку, вызывающую проблему. Глядя на строку, может быть очевидно, в чем проблема. Если нет, попробуйте функцию DUMP, чтобы просмотреть байты в данных.

Возможно, что данные в числовом столбце не соответствуют определению столбца. Обычно это ошибка, возможно повреждение диска, иногда странные данные, созданные через OCI. Вы можете попробовать сделать

SELECT COUNT(*) FROM PERSON WHERE ID != TRUNC(ID); 

Если в вашей базе данных используется многобайтовый набор символов, это может привести к путанице в строках. Также, если в строке есть нестандартные символы (например, ASCII 0-31)

0 голосов
/ 22 января 2009

Кроме того, вы должны рассмотреть возможность использования Apache Commons DBUtils для закрытия ваших ресурсов. Это позволит вам заменить содержимое вашего предложения finally одной строкой:

DBUtils.closeQuietly(con, pstmt, rs);
0 голосов
/ 22 января 2009

Сначала попробуйте getMaxFieldSize для запроса, чтобы вы точно знали, каков максимальный размер поля. Я не программист Oracle (PostgreSQL), но я знаю, что Oracle должен иметь одну из, если не лучшую, поддержку метаданных. Измените ваш SQL-запрос с ограничением максимального размера поля. Это, по крайней мере, приведет вас на полпути.

public int getMaxFieldSize () выдает SQLException

Returns the maximum number of bytes allowed for any column value.

Это максимальное количество байты, которые могут быть возвращены для любого значение столбца Ограничение применяется только БИНАРНЫЙ, VARBINARY, LONGVARBINARY, CHAR, VARCHAR и LONGVARCHAR колонны. Если предел превышен, лишние данные отбрасываются молча.

Returns:
    the current max column size limit; zero means unlimited
Throws:
    SQLException - if a database access error occurs
0 голосов
/ 20 января 2009

Для меня первое, что нужно сделать, это посмотреть на «ошибочные» данные, изменив ваш цикл, чтобы отобразить строку, которая вызывает исключение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...