Вставка больших текстовых данных в postgres с помощью python

Я пытаюсь выполнить массовую вставку длинных строк xml в виде текста в базу данных postgresql 9.1. Я использую Python 3.2 и pyscopg2. Я заключаю строку xml в $$ и использую именованную переменную в строке запроса. Например:

query = "insert into cms_object_metadata (cms_object_id, cms_object_metadata_data, cms_object_metadata_type_id, \
         cms_object_metadata_status_id) values ((select id from cms_objects where cms_object_ident = %(objIdent)s), \
         $$%(objMetaString)s$$, (select id from cms_object_metadata_types where cms_object_metadata_type_name = 'PDAT'), \
         (select id from cms_object_metadata_status where cms_object_metadata_status_name = 'active'))"

Затем я создаю объект словаря следующим образом:

dataDict = {'objIdent':objIdent, 'objMetaString':objMetaString}

передавая значения objIdent и objMetaString. Я делаю вставку со следующим кодом:

dbCursor.execute(query, dataDict)

Когда он вставляет значение objMetaString в базу данных, он заключает строку в одинарные кавычки. Если я добавляю значения в строку запроса и выполняю вставку без именованной переменной, это не так. Например:

query = "insert into cms_object_metadata (cms_object_id, cms_object_metadata_data, cms_object_metadata_type_id, \
         cms_object_metadata_status_id) values ((select id from cms_objects where cms_object_ident = %s), \
         $$%s$$, (select id from cms_object_metadata_types where cms_object_metadata_type_name = 'PDAT'), \
         (select id from cms_object_metadata_status where cms_object_metadata_status_name = 'active'))" % (objIdent, objMetaString)

и вставка:

dbCursor.execute(query)

Мой вопрос заключается в том, как выполнить массовую вставку больших текстовых данных с использованием именованных переменных и $$. Я действительно не хочу предварительно или после обработки этой строки, если это возможно, поскольку они могут быть большими и содержать неизвестное количество либо одинарных кавычек, либо других символов, которые необходимо будет разделить. Я прочитал следующую документацию и искал ответ в stackoverflow, но не нашел решения:


person mcfar    schedule 28.10.2011    source источник
comment
Что делает вас настолько уверенным, что ваши большие текстовые данные не содержат $$, чтобы вам не пришлось избегать и этого?   -  person Peter Eisentraut    schedule 28.10.2011
comment
Если мое понимание, прочитанное мной, верно, то вам не нужно беспокоиться о каких-либо $ в строке. Цитата из документов Postgresql: 4.1.2.4. Строковые константы в долларовых кавычках. Обратите внимание, что внутри строки в долларовых кавычках можно использовать одинарные кавычки без экранирования. Действительно, никакие символы внутри строки в долларовых кавычках никогда не экранируются: содержимое строки всегда записывается буквально. Обратная косая черта не является специальной, как и знаки доллара, если только они не являются частью последовательности, соответствующей открывающему тегу.   -  person mcfar    schedule 31.10.2011
comment
Вы должны волноваться. Посмотрите последнее предложение того, что вы процитировали.   -  person Peter Eisentraut    schedule 01.11.2011
comment
Вы правы, но мне все еще интересно, как лучше всего справиться с этим, нужно ли мне анализировать всю строку и экранировать там, где это необходимо, а не использовать синтаксис $$. Я не против проверить открывающий тег для них, но надеялся избежать разбора всего текста в каждой строке. В нашем конкретном случае мы создаем xml и вставляем значения, поэтому у меня есть некоторый контроль над xml, но не над значениями. Должен быть стандартный способ сделать это???   -  person mcfar    schedule 01.11.2011
comment
Стандартный способ сделать это — позволить драйверу справиться с этим, как в вашем первом примере кода.   -  person Peter Eisentraut    schedule 01.11.2011
comment
Спасибо за помощь, Питер, это то, что я в конечном итоге сделал, но затем мне приходится удалять одинарные кавычки из строк xml, когда я вытаскиваю их из базы данных и использую. Это не ужасное решение, но я надеялся, что есть способ сделать это без этого дополнительного шага.   -  person mcfar    schedule 01.11.2011


Ответы (1)


Подведение итогов ветки комментариев. Сделай это:

query = "insert into cms_object_metadata (cms_object_id, cms_object_metadata_data, cms_object_metadata_type_id, \
         cms_object_metadata_status_id) values ((select id from cms_objects where cms_object_ident = %(objIdent)s), \
         %(objMetaString)s, (select id from cms_object_metadata_types where cms_object_metadata_type_name = 'PDAT'), \
         (select id from cms_object_metadata_status where cms_object_metadata_status_name = 'active'))"

dataDict = {'objIdent':objIdent, 'objMetaString':objMetaString}

dbCursor.execute(query, dataDict)

Не заключайте в кавычки заполнитель %(objMetaString)s в запросе. Задача водителя — указать значение, если это необходимо.

person Peter Eisentraut    schedule 02.11.2011