Ошибка: столбец "test" не существует

Почему не работает? Как исправить?

import psycopg2
from psycopg2 import Error

tableLit = 'gt_zavod_1_92_25'

try:

    connection = psycopg2.connect(user="postgres",
                                password="Best4KamCH",
                                host="127.0.0.1",
                                port="5432",
                                database="postgres")
    cursor = connection.cursor()

    test = ['800']

    postgres_insert_query_z1 = ("""SELECT liter FROM {table} WHERE cm = test""")
    cursor.execute(postgres_insert_query_z1.format(table=tableLit))
    hhz = cursor.fetchall()

    print(hhz)

    if connection:
        online_base = 1
        cursor.close()
        connection.close()
        print("Соединение с PostgreSQL закрыто")

except (Exception, Error) as error:
    print("Ошибка при работе с PostgreSQL", error)

Выдает ошибку:

Ошибка при работе с PostgreSQL ОШИБКА:  столбец "test" не существует
LINE 1: SELECT liter FROM gt_zavod_1_92_25 WHERE cm = test[0]
                                                      ^

Ответы (2 шт):

Автор решения: Sergey

Когда Вы делаете передаёте SQL-серверу строку postgres_insert_query_z1:

cursor.execute(postgres_insert_query_z1.format(table=tableLit))

то говорите, что имя таблицы надо взять из переменной table=tableLit и поэтому на сервер приходит строка, начинающаяся с

SELECT liter FROM gt_zavod_1_92_25 

Но с окнчанием этой строки - проблема. Там написано WHERE cm = test, но SQL сервер ничего не знает о том. что такое test. Поэтому, он пытается найти это имя в списке колонок своих таблиц. Такого имени нет. Вот он Вам и говорит:

PostgreSQL ОШИБКА:  столбец "test" не существует

Решение очевидно. Надо в исходной строке заменить "test" на "{test}", а при отправке этой строки на сервер указать конкретное значение этой переменной:

value=1234
.format(table=tableLit,test=value)
→ Ссылка
Автор решения: MaxU

Наиболее правильный подход в данном случае - это воспользоваться форматированием для подстановки имени таблицы и параметризированным запросом для подстановки значений литералов:

qry_template = """SELECT liter FROM {table} WHERE cm = %s"""
...
cursor.execute(qry_template.format(table=tableLit), [test[0]])

Данный подход имеет несколько преимуществ:

  1. обезопасит вас от SQL Injections
  2. DB драйвер сам позаботится об экранировании и форматировании. Например если вы передаете переменную типа datetime в качестве параметра, то вам не придется специально форматировать дату/время.
  3. в большинстве БД параметризированные запросы будут выполняться быстрее в цикле, т.к. такой запрос будет проверен на правильность синтаксиса, на права доступа к DB объектам и распарсен только один раз и сохранен в памяти БД.

NOTE: параметризированные запросы не позволяют указывать имена SQL объектов (например имена таблиц, столбцов, индексов, etc.) в качестве параметров.

→ Ссылка