Я пишу инструмент переноса данных db с использованием языка выражения SQLAlchemy в качестве основного инструмента.
Моя исходная база данных может быть в UTF8 или может быть в SQL_ASCII. Моя целевая БД всегда будет в UTF8.
Я использую драйвер psycopg2 в SQLAlchemy 0.6.6
Мой общий процесс миграции выглядит следующим образом:
for t in target_tables:
log.info("Migrating data from %s", t.fullname)
source = self.source_md.tables[self.source_schema + "." + t.name]
for row in source.select().execute():
with sql_logging(logging.INFO):
conn.execute(t.insert(), row)
Если я не устанавливаю что-либо, связанное с кодированием в двигателях, я получаю это, когда я повторяю результаты select()
:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)
Если я устанавливаю use_native_unicode=True, encoding='utf-8'
в движках, я получаю это, когда пытаюсь вставить новую строку:
sqlalchemy.exc.DataError: (DataError) invalid byte sequence for encoding "UTF8": 0xeb6d20
HINT: This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".
'INSERT INTO project_ghtests_survey000005.employees (first_name, employee_id) VALUES (%(first_name)s, %(employee_id)s)' {'first_name': 'Art\xebm', 'employee_id': '1234'}
Чтобы сделать запросы более быстрыми, вот программный стек в игре:
SQL_ASCII
UTF8
Оказывается, что решение было установить соединение client_encoding с 'latin1'
Я выполнил это с помощью PoolListener следующим образом:
class EncodingListener(PoolListener):
def connect(self, dbapi_con, con_record):
with closing(dbapi_con.cursor()) as cur:
cur.execute('show client_encoding')
encoding = cur.fetchone()[0]
if encoding.upper() == 'UTF8':
return
dbapi_con.set_client_encoding('latin1')
Поскольку UTF-8 обратно совместим с UTF-8, зачем использовать SQL_ASCII
isntead UTF8
?
Я думаю, что ваши проблемы с кодированием, вероятно, больше похожи на latin1
или аналогичные кодировки. Не с ASCII
до UTF8
.
SQL_ASCII
илиUTF8
для исходной базы данных, посколькуUTF8
обратно совместим сASCII
.