#python #postgresql #psycopg2
#python #postgresql #psycopg2
Вопрос:
Я пытаюсь выполнить массовую вставку длинных 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, но не нашел решения:
Комментарии:
1. Почему вы так уверены, что ваши большие текстовые данные не содержат
$$
, чтобы вам не приходилось их избегать?2. Если я правильно понял, прочитав это, вам не нужно беспокоиться о каких-либо $ в строке. Цитата из документов Postgresql: 4.1.2.4. Строковые константы, заключенные в долларовые кавычки — Обратите внимание, что внутри строки, заключенной в долларовые кавычки, одинарные кавычки можно использовать без необходимости экранирования. Действительно, никакие символы внутри строки, заключенной в долларовые кавычки, никогда не экранируются: содержимое строки всегда записывается буквально. Обратная косая черта не является специальной, как и знаки доллара, если только они не являются частью последовательности, соответствующей открывающему тегу.
3. Вам следует беспокоиться. Смотрите последнее предложение того, что вы процитировали.
4. Вы правы, но я все еще задаюсь вопросом, как лучше всего справиться с этим, нужно ли мне анализировать полную строку и экранировать, где это необходимо, и не использовать синтаксис $$. Я не против проверить открывающий тег для них, но надеялся избежать синтаксического анализа всего текста в каждой строке. В нашем конкретном случае мы создаем xml и вставляем значения, поэтому у меня есть некоторый контроль над xml, но не над значениями. Должен быть стандартный способ сделать это???
5. Стандартный способ сделать это — позволить драйверу обработать это, как в вашем первом примере кода.
Ответ №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
заполнитель в кавычки в своем запросе. При необходимости указать значение — задача драйвера.