Команда Postgres truncate SQL: передача имени динамической таблицы

Я работаю над веб-проектом Python, используя базу данных postgres в качестве бэкэнда с пакетом psycopg2.

Раньше я пытался static запросить команду truncate для демонстрационных целей, после того, как она заработала, я попытался сделать это dynamic, тем самым пропустив table name.

def clear_tables(query: str, vars_list: list[Any]):
   # psycog 2 connection engine code
   
   cursor.executemany(query=query, vars_list=vars_list)
   
   conn.commit()
   
   
def foo():

   vars_list: list[Any] = list()

   table_name: str = "person"

   record: tuple[Any] = (table_name,)

   vars_list.append(record)

   query = """
       TRUNCATE TABLE %s RESTART IDENTITY;
       """
     
   clear_tables(query=query, vars_list=vars_list)      

При выполнении получаю ошибку. Каким-то образом table name получает нежелательные ' одинарные кавычки

psycopg2.errors.SyntaxError: syntax error at or near "'person'"
LINE 2:        TRUNCATE TABLE 'person' RESTART IDENTITY;

Как убрать эти цитаты?

Используйте %I (идентификатор) вместо %s (строка) в своем заявлении. Итак: TRUNCATE TABLE %I RESTART IDENTITY;

Belayer 20.04.2023 19:33

Я на много лет отстал от PostgreSQL, но обратите внимание, что в базах данных SQL обычно не все поля могут быть параметризованы в первую очередь. Частью смысла подготовленных операторов является построение плана запроса перед его выполнением; но если вы не знаете, какая таблица, вы не сможете найти, какие индексы применяются, и в противном случае у вас не будет достаточно, чтобы начать планирование. (Да, это обоснование не применимо к TRUNCATE, но в целом вы не позволите ненадежному коду решать, какое имя таблицы усекать в первую очередь, поэтому многие доводы в пользу подготовленных операторов не учитываются. не применяется)

Charles Duffy 20.04.2023 19:37

Привет Belayer, Спасибо. Я пытался использовать его, но как-то это не сработало. При дальнейшем поиске я получил AsIS расширение от psycog2, сейчас попробую.

winter 20.04.2023 21:06

Привет, Чарльз, спасибо. Хорошо сказано и я с вами согласен. Я новичок в sql, мне нравится учиться и читать о том, как писать хорошие postgres/sql запросы. У вас есть или вы хотите предложить некоторые open source/free resources or code snippets. Как вы упомянули, некоторые компоненты/части запросов sql не должны быть параметризованы, в этом есть смысл.

winter 20.04.2023 21:08

@Belayer %I и %L — это заполнители, используемые функцией format(), доступной в Postgres. Они не работают с Psycopg2.

filiprem 21.04.2023 02:02
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
5
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Внесите следующие изменения и повторите попытку:

query = "TRUNCATE TABLE {tableName} RESTART IDENTITY;"
cursor.execute(sql.SQL(query).format(tableName=sql.Literal("person"))

Помимо предотвращения целого ряда проблем с безопасностью, этот стиль форматирования предотвращает атаки SQL Injection. В будущем лучше использовать этот стиль или некоторые другие возможные, используя встроенный .format().

Для дальнейшего чтения, пожалуйста, проверьте документацию.

Ответ принят как подходящий

Это работает и защищено от SQL-инъекций:

import psycopg2
from psycopg2 import sql


def truncate(conn: psycopg2.extensions.connection, schema: str, table: str):
    query = sql.SQL("TRUNCATE {schema}.{table} RESTART IDENTITY").format(
        schema=sql.Identifier(schema), table=sql.Identifier(table)
    )
    with conn.cursor() as cur:
        cur.execute(query)


conn = psycopg2.connect()
truncate(conn, "public", "foo")

Другие вопросы по теме

Похожие вопросы