У меня есть ситуация, когда мне нужно вставить более 4000 символов в Oracle VARCHAR, и мне было рекомендовано не использовать CLOB. Предложенное решение состояло в том, чтобы разделить его на 2 столбца, по 4000 и 8000. Я сделал код динамическим, чтобы можно было обрабатывать количество столбцов X для повторного использования. Он работал отлично, проходил тестирование и т.д., Пока не был развернут, и кто-то скопировал и вставил из продукта Microsoft, и он сломался, потому что в функции было сгенерировано более 4000 байтов. Я не рассматривал Unicode.
Я попробовал несколько идей, чтобы решить эту проблему, прежде чем остановиться на одном, где я начинаю с 4000 символов, и если длина байта превышает 4000, удалите символ и снова проверьте длину байта. Это работает, но мне интересно, есть ли лучшее решение. Функция также изменяет имена столбцов с 'column' на 'column1', 'column2',... и т.д.
text = data[key]
index = 1
while text:
length = 4000
while len(text[0:length].encode('utf-8')) > 4000:
length -= 1
data['{}{}'.format(key, index)] = text[0:length]
text = text[length:]
index += 1
del data[key]
Проверьте, действовал ли ваш совет по отношению к объектам CLOB, или он основан на старой информации о доступе к объектам LOB с использованием локаторов.
Лучшая практика для "маленьких" CLOB в cx_Oracle - представлять их как строки: ваш код будет простым и все же эффективным. Смотрите пример https://github.com/oracle/python-cx_Oracle/blob/master/samples/ReturnLobsAsStrings.py
Другое решение состоит в том, чтобы использовать последнюю версию Oracle DB, которая поддерживает 32K VARCHAR2.
Я закончил тем, что соединил ссылку Дж. Андерсона с моим кодом. Он более эффективен в том смысле, что он не кодирует для каждой проверки длины.
encoded_text = data[key].encode('utf-8')
index = 1
while encoded_text:
length = min(4000, len(encoded_text))
if len(encoded_text) > 4000:
while (encoded_text[length] & 0xc0) == 0x80:
length -= 1
data['{}{}'.format(key, index)] = encoded_text[:length].decode('utf-8')
encoded_text = encoded_text[length:]
index += 1
del data[key]
Я также поиграл с идеей использовать encode('unicode-escape')
чтобы обойти проблему с юникодом, но это может потенциально более чем удвоить мою длину строки.