Я использую API импорта Google Cloud для загрузки файла CSV из Google Cloud Storage в базу данных Cloud SQL MySQL 5.7:
https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/instances/import
API импорта генерирует команду LOAD DATA INFILE для базы данных MySQL, которая принимает набор символов utf8. Тем не менее, данные в моих файлах CSV используют кодировку utf8mb4, которая является надмножеством utf8. Это приводит к сбою процесса загрузки, когда некоторые строки не могут быть закодированы в 'utf8':
Exception: CloudSQL Exception: {'kind': 'sql#operation', 'selfLink': 'https://www.googleapis.com/sql/v1beta4/projects/***', 'targetProject': '***', 'targetId': '***', 'targetLink': 'https://www.googleapis.com/sql/v1beta4/projects/***', 'name': '0211c99e-0633-42f1-9ee1-069473308273', 'operationType': 'IMPORT', 'status': 'RUNNING', 'user': '***', 'insertTime': '2019-01-14T02:36:39.861Z', 'startTime': '2019-01-14T02:36:39.972Z', 'error': {'kind': 'sql#operationErrors', 'errors': [{'kind': 'sql#operationError', 'code': 'ERROR_RDBMS', 'message': "Import CSV error: Error 1300: Invalid utf8 character string: ''Afikanisitani|'Apekanikana|A Phu Han (Afghanistan)|A Phú Hãn '\n"}]}, 'importContext': {'kind': 'sql#importContext', 'uri': '***', 'database': '**', 'importUser': '', 'csvImportOptions': {'table': '***'}}}
Соответствующий фрагмент: "'message':" Ошибка импорта CSV: Ошибка 1300: Неверная строка символов utf8: "
Есть ли способ добавить 'utf8mb4' CHARACTER SET, используя API импорта (или любой другой набор символов в этом отношении)?
Я попытался поэкспериментировать с добавлением 'набора символов': 'utf8mb4' в словаре 'csvImportOptions', но похоже, что API импорта ожидает только ключи 'table' и 'columns' в этом словаре.
Обратите внимание: если я напрямую запускаю команду LOAD DATA INFILE из клиента MySQL, я могу импортировать CSV без проблем:
LOAD DATA INFILE 'myCSVFile.csv'
INTO TABLE 'my table'
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
IGNORE 1 ROWS
from pprint import pprint
from googleapiclient import discovery
from oauth2client.client import GoogleCredentials
credentials = GoogleCredentials.get_application_default()
service = discovery.build('sqladmin', 'v1beta4', credentials=credentials)
# Project ID of the project that contains the instance.
project = 'my-project' # TODO: Update placeholder value.
# Cloud SQL instance ID. This does not include the project ID.
instance = 'my-instance' # TODO: Update placeholder value.
instances_import_request_body = {
"importContext": {
"kind": "sql#importContext",
"fileType": "CSV",
"uri": gcs_uri,
"database": database,
"csvImportOptions": {
"table": table
}
}
}
request = service.instances().import_(project=project, instance=instance, body=instances_import_request_body)
response = request.execute()
ДОПОЛНИТЕЛЬНАЯ ТОЧКА ДАННЫХ
Для меня очевидно, что запрос LOAD DATA INFILE, который генерирует API Google, по умолчанию использует набор символов utf8.
Сбой с таким же сообщением об ошибке, как API
LOAD DATA INFILE 'problematic.csv'
INTO TABLE my_table
**CHARACTER SET utf8**
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
ESCAPED BY '\"'
ERROR 1300 (HY000): Invalid utf8 character string: ''Afikanisitani|'Apekanikana|A Phu Han (Afghanistan)|A Phú Hãn '
Работает:
LOAD DATA INFILE 'problematic.csv'
INTO TABLE my_table
**CHARACTER SET utf8mb4**
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
ESCAPED BY '\"'
Query OK, 75641 rows affected (1.14 sec)
Records: 75641 Deleted: 0 Skipped: 0 Warnings: 0
Документация здесь неверна: https://cloud.google.com/sql/docs/mysql/import-export/importing
LOAD DATA INFILE ... ***CHARACTER SET 'utf8mb4'***
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\"'.