Введите имя столбца в качестве параметра PostgreSQL, используя psycopg2

Я пытаюсь добавить столбцы в таблицу, используя psycopg2

row1 Ниже приведен список имен столбцов, которые должны быть добавлены в таблицу. Я могу сделать это вручную, но когда я пытаюсь сделать это программно, я получаю сообщение об ошибке.

for c in row1:
    cur.execute("ALTER TABLE HHV2PUB ADD COLUMN %s text", (c,))

Ошибка:

    cur.execute("ALTER TABLE HHV2PUB ADD COLUMN %s text", (c,))
psycopg2.ProgrammingError: syntax error at or near "'HOUSEID'"
LINE 1: ALTER TABLE HHV2PUB ADD COLUMN 'HOUSEID' text

Я предполагаю, что это имеет какое-то отношение к одинарным кавычкам ''

Ответ 1

Как и в Psycopg 2.7, существует безопасный sql module:

from psycopg2 import sql

query = sql.SQL("alter table t add column {} text")

row1 = ('col1', 'col2')
for c in row1:
    cursor.execute(query.format(sql.Identifier(c)))

С 2.6 и ранее:

Используйте psycopg2.extensions.AsIs

Адаптер соответствует протоколу ISQLQuote, полезному для объектов, строковое представление которых уже действует как представление SQL.

import psycopg2
from psycopg2.extensions import AsIs

conn = psycopg2.connect("host=localhost4 port=5432 dbname=cpn")
cursor = conn.cursor()

query = "alter table t add column %s text"

row1 = ('col1', 'col2')
for c in row1:
    cursor.execute(query, (AsIs(c),))
conn.commit()

Ответ 2

Вы не можете использовать параметры SQL для имен объектов SQL. Значения параметров кода SQL явно указаны так, что их нельзя интерпретировать как таковые; это одна из основных причин использования параметров SQL в противном случае.

Здесь вам понадобится использовать интерполяцию строк. Будьте предельно осторожны, чтобы вы не использовали пользовательский ввод для создания c здесь:

for c in row1:
    cur.execute("ALTER TABLE HHV2PUB ADD COLUMN %s text" % c)

Psycopg2 дает вам метод для обозначения параметров как "уже экранированных" с помощью psycopg2.extensions.AsIs(), но это намерение вместо этого используется вместо уже сохраненных данных.

Лучше всего использовать расширение psycopg2.sql для управления правильным экранированием идентификатора:

from psycopg2 import sql

for c in row1:
    cur.execute(
        sql.SQL("ALTER TABLE HHV2PUB ADD COLUMN {} text").format(
            sql.Identifier(c)))