Чтение некорректных файлов CSV
Файлы CSV могут иметь самые разные форматы, и некоторые из них содержат множество ошибок, что затрудняет их чистое чтение. Чтобы помочь пользователям читать такие файлы, DuckDB поддерживает подробные сообщения об ошибках, возможность пропускать некорректные строки и возможность сохранения некорректных строк во временной таблице для упрощения этапа очистки данных.
Структурные ошибки
DuckDB поддерживает обнаружение и пропуск нескольких различных структурных ошибок. В этом разделе мы рассмотрим каждую ошибку с примером. Для примеров рассмотрим следующую таблицу:
CREATE TABLE people (name VARCHAR, birth_date DATE);
DuckDB обнаруживает следующие типы ошибок:
-
CAST: Ошибки приведения типов возникают, когда столбец в файле CSV не может быть приведен к ожидаемому типу схемы. Например, строкаPedro,The 90sвызовет ошибку, так как строкуThe 90sнельзя привести к дате. -
MISSING COLUMNS: Эта ошибка возникает, если строка в файле CSV содержит меньше столбцов, чем ожидалось. В нашем примере ожидается два столбца; следовательно, строка с одним значением, напримерPedro, вызовет эту ошибку. -
TOO MANY COLUMNS: Эта ошибка возникает, если строка в файле CSV содержит больше столбцов, чем ожидалось. В нашем примере любая строка с более чем двумя столбцами вызовет эту ошибку, например,Pedro,01-01-1992,pdet. -
UNQUOTED VALUE: Значения в кавычках в строках CSV всегда должны быть не в кавычках в конце; если значение в кавычках остается в кавычках на протяжении всей строки, это вызовет ошибку. Например, предположим, что наш сканер используетquote='"', строка"pedro"holanda, 01-01-1992будет содержать ошибку невыведенного значения. -
LINE SIZE OVER MAXIMUM: В DuckDB есть параметр, который устанавливает максимальный размер строки в файле CSV, который по умолчанию установлен в2,097,152байт. Предположим, что наш сканер установлен наmax_line_size = 25, строкаPedro Holanda, 01-01-1992вызовет ошибку, так как она превышает 25 байт. -
INVALID UNICODE: DuckDB поддерживает только строки UTF-8; следовательно, строки, содержащие символы, не являющиеся UTF-8, будут вызывать ошибку. Например, строкаpedro\xff\xff, 01-01-1992будет проблематичной.
Структура сообщения об ошибке CSV
По умолчанию, при чтении CSV, если встречаются какие-либо структурные ошибки, сканер немедленно остановит процесс сканирования и выведет ошибку пользователю. Эти ошибки разработаны для предоставления максимально возможной информации, чтобы пользователи могли напрямую оценить их в своём файле CSV.
Это пример полного сообщения об ошибке:
Conversion Error: CSV Error on Line: 5648
Original Line: Pedro,The 90s
Error when converting column "birth_date". date field value out of range: "The 90s", expected format is (DD-MM-YYYY)
Column date is being converted as type DATE
This type was auto-detected from the CSV file.
Possible solutions:
* Override the type for this column manually by setting the type explicitly, e.g. types={'birth_date': 'VARCHAR'}
* Set the sample size to a larger value to enable the auto-detection to scan more values, e.g. sample_size=-1
* Use a COPY statement to automatically derive types from an existing table.
file= people.csv
delimiter = , (Auto-Detected)
quote = " (Auto-Detected)
escape = " (Auto-Detected)
new_line = \r\n (Auto-Detected)
header = true (Auto-Detected)
skip_rows = 0 (Auto-Detected)
date_format = (DD-MM-YYYY) (Auto-Detected)
timestamp_format = (Auto-Detected)
null_padding=0
sample_size=20480
ignore_errors=false
all_varchar=0 Первый блок предоставляет информацию о месте возникновения ошибки, включая номер строки, исходную строку CSV и проблемный столбец:
Conversion Error: CSV Error on Line: 5648 Original Line: Pedro,The 90s Error when converting column "birth_date". date field value out of range: "The 90s", expected format is (DD-MM-YYYY)
Второй блок предоставляет потенциальные решения:
Column date is being converted as type DATE
This type was auto-detected from the CSV file.
Possible solutions:
* Override the type for this column manually by setting the type explicitly, e.g. types={'birth_date': 'VARCHAR'}
* Set the sample size to a larger value to enable the auto-detection to scan more values, e.g. sample_size=-1
* Use a COPY statement to automatically derive types from an existing table. Поскольку тип этого столбца был определён автоматически, предлагается определить столбец как VARCHAR или полностью использовать набор данных для определения типа.
Наконец, последний блок представляет некоторые параметры, используемые в сканере, которые могут вызывать ошибки, указывая, были ли они определены автоматически или установлены пользователем вручную.
Использование параметра ignore_errors
Существуют случаи, когда файлы CSV могут содержать несколько структурных ошибок, и пользователи просто хотят пропустить их и прочитать корректные данные. Чтение файлов CSV с ошибками возможно с помощью параметра ignore_errors. При использовании этого параметра строки, содержащие данные, которые в противном случае вызвали бы ошибку анализатора CSV, будут пропущены. В нашем примере мы продемонстрируем ошибку приведения типов, но обратите внимание, что любая из ошибок, описанных в разделе «Структурные ошибки», приведет к пропусканию некорректной строки.
Например, рассмотрим следующий файл CSV, faulty.csv:
Pedro,31
Oogie Boogie, three
Если вы читаете файл CSV, указав, что первый столбец является VARCHAR, а второй столбец - INTEGER, загрузка файла завершится с ошибкой, так как строка three не может быть преобразована в INTEGER.
Например, следующий запрос вызовет ошибку приведения типов.
FROM read_csv('faulty.csv', columns = {'name': 'VARCHAR', 'age': 'INTEGER'}); Однако, при ignore_errors установленной, вторая строка файла пропускается, выводит только полную первую строку. Например:
FROM read_csv(
'faulty.csv',
columns = {'name': 'VARCHAR', 'age': 'INTEGER'},
ignore_errors = true
); Вывод:
| name | age |
|---|---|
| Pedro | 31 |
Следует отметить, что анализатор CSV подвержен оптимизации сжатия проекции. Следовательно, если мы выберем только столбец «имя», обе строки будут считаться корректными, так как ошибка приведения типов для столбца «возраст» никогда не произойдёт. Например:
SELECT name
FROM read_csv('faulty.csv', columns = {'name': 'VARCHAR', 'age': 'INTEGER'}); Вывод:
| name |
|---|
| Pedro |
| Oogie Boogie |
Получение некорректных строк CSV
Возможность чтения файлов CSV с ошибками важна, но для многих операций очистки данных также необходимо точно знать, какие строки повреждены и какие ошибки обнаружил анализатор. В таких ситуациях можно использовать функцию DuckDB «Таблица отклонений CSV». По умолчанию эта функция создаёт две временные таблицы.
-
reject_scans: Содержит информацию о параметрах сканера CSV -
reject_errors: Содержит информацию о каждой некорректной строке CSV и о том, в каком сканере CSV она произошла.
Обратите внимание, что любые ошибки, описанные в разделе «Структурные ошибки», будут храниться в таблицах отклонений. Также, если у строки есть несколько ошибок, будет храниться несколько записей для одной строки, по одной на каждую ошибку.
Таблицы отклонений сканирования
Таблица отклонений сканирования CSV возвращает следующую информацию:
| Имя столбца | Описание | Тип |
|---|---|---|
scan_id | Внутренний идентификатор, используемый в DuckDB для представления сканера | UBIGINT |
file_id | Сканирование может происходить по нескольким файлам, поэтому file_id представляет уникальный файл в сканере | UBIGINT |
file_path | Путь к файлу | VARCHAR |
delimiter | Разделитель, например; | VARCHAR |
quote | Знак кавычек, например " | VARCHAR |
escape | Знак кавычек, например " | VARCHAR |
newline_delimiter | Разделитель новой строки, например \r\n | VARCHAR |
skip_rows | Если какие-либо строки были пропущены из начала файла | UINTEGER |
has_header | Если файл имеет заголовок | BOOLEAN |
columns | Схема файла (т.е. все имена и типы столбцов) | VARCHAR |
date_format | Формат, используемый для дат | VARCHAR |
timestamp_format | Формат, используемый для временных меток | VARCHAR |
user_arguments | Дополнительные параметры сканера, установленные пользователем вручную | VARCHAR |
Таблицы отклонений ошибок
Таблица отклонений ошибок CSV возвращает следующую информацию:
| Имя столбца | Описание | Тип |
|---|---|---|
scan_id | Внутренний идентификатор, используемый в DuckDB для представления сканера, используется для объединения с таблицами отбракованных сканирований | UBIGINT |
file_id | Поле file_id представляет собой уникальный файл в сканере, используется для объединения с таблицами отбракованных сканирований | UBIGINT |
line | Номер строки в файле CSV, где произошла ошибка. | UBIGINT |
line_byte_position | Позиция байта начала строки, где произошла ошибка. | UBIGINT |
byte_position | Позиция байта, где произошла ошибка. | UBIGINT |
column_idx | Если ошибка произошла в определенном столбце, индекс столбца. | UBIGINT |
column_name | Если ошибка произошла в определенном столбце, имя столбца. | VARCHAR |
error_type | Тип ошибки, которая произошла. | ENUM |
csv_line | Исходная строка CSV. | VARCHAR |
error_message | Сообщение об ошибке, сгенерированное DuckDB. | VARCHAR |
Параметры
Ниже перечислены параметры, используемые в функции read_csv для настройки таблицы отбракованных CSV.
| Имя | Описание | Тип | Значение по умолчанию |
|---|---|---|---|
store_rejects | Если установлено в true, все ошибки в файле будут пропущены и сохранены в стандартных временных таблицах отбракованных данных. | BOOLEAN | False |
rejects_scan | Имя временной таблицы, в которой хранится информация о сканировании некорректного CSV-файла. | VARCHAR | reject_scans |
rejects_table | Имя временной таблицы, в которой хранится информация о некорректных строках CSV-файла. | VARCHAR | reject_errors |
rejects_limit | Верхний предел количества некорректных записей из CSV-файла, которые будут записаны в таблицу отбракованных данных. 0 используется, если ограничение применять не нужно. | BIGINT | 0 |
Чтобы сохранить информацию о некорректных строках CSV-файла в таблице отбракованных данных, пользователю необходимо установить параметр store_rejects в значение true. Например:
FROM read_csv(
'faulty.csv',
columns = {'name': 'VARCHAR', 'age': 'INTEGER'},
store_rejects = true
); Затем можно запросить обе таблицы reject_scans и reject_errors, чтобы получить информацию об отброшенных кортежах. Например:
FROM reject_scans;
Вывод:
| scan_id | file_id | путь_к_файлу | разделитель | кавычки | экранирование | разделитель_строк | пропуск_строк | имеет_заголовок | столбцы | формат_даты | формат_временной_метки | пользовательские_аргументы |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5 | 0 | faulty.csv | , | " | " | \n | 0 | false | {'name': 'VARCHAR','age': 'INTEGER'} | store_rejects=true |
FROM reject_errors;
Вывод:
| scan_id | file_id | строка | позиция_байта_строки | позиция_байта | индекс_столбца | имя_столбца | тип_ошибки | строка_csv | сообщение_об_ошибке |
|---|---|---|---|---|---|---|---|---|---|
| 5 | 0 | 2 | 10 | 23 | 2 | возраст | CAST | Oogie Boogie, three | Ошибка при преобразовании столбца "возраст". Не удалось преобразовать строку " three" в 'INTEGER' |
© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/data/csv/reading_faulty_csv_files.html