#python #psycopg2
#python #psycopg2
Вопрос:
Я пытаюсь динамически создавать таблицы с помощью psycopg2.sql, я написал функцию, которая принимает список кортежей, состоящий из имени столбца и типа данных столбца, затем я создаю строку, вызываю ее query, используя «{}» в качестве заполнителей, подобных этому:
create table {} ({} {}, {} {} ...);
Я сглаживаю список кортежей, чтобы элементы в результирующем списке соответствовали порядку, в котором я хочу вставить их в строку запроса, и использую результирующий список в качестве аргумента в sql.SQL(query).format(…)
Результирующий экземпляр sql.Composed выглядит следующим образом:
Composed([SQL('create table '), Identifier('games'), SQL(' ( '), Identifier('score_loser'), SQL(' '), Identifier('integer'), SQL(' , '), Identifier('playoffs'), SQL(' '), Identifier('boolean'), SQL(' , '), Identifier('record_loser'), SQL(' '), Identifier('integer[]'), SQL(' , '), Identifier('broadcast'), SQL(' '), Identifier('varchar(20)'), SQL(' , '), Identifier('date'), SQL(' '), Identifier('date'), SQL(' , '), Identifier('id'), SQL(' '), Identifier('varchar (30)'), SQL(' , '), Identifier('home_team'), SQL(' '), Identifier('varchar (50)'), SQL(' , '), Identifier('record_winner'), SQL(' '), Identifier('integer[]'), SQL(' , '), Identifier('winner'), SQL(' '), Identifier('varchar (50)'), SQL(' , '), Identifier('loser'), SQL(' '), Identifier('varchar (50)'), SQL(' , '), Identifier('score_winner'), SQL(' '), Identifier('integer'), SQL(' , primary key ('), Identifier('id'), SQL(') );')])
Но когда я пытаюсь выполнить этот экземпляр sql.Composed, я получаю сообщение об ошибке, что «integer» не является типом, где «integer» был элементом в списке, который я передал функции format.
Невозможно ли также динамически передавать типы переменных с помощью psycopg2.sql, или, если это возможно, не могли бы вы рассказать мне, как это сделать?
Ответ №1:
У меня была похожая проблема. Я решил это, смешав состав строк, format() и генераторы списков.
data = (('column_name_1','VARCHAR(2)'), ('column_name_2','INT'))
data = ['%s %s' % (x[0], x[1]) for x in data]
columns_string = ', '.join([x for x in data])
Здесь columns_string =
‘имя_столбца 1 VARCHAR(2), имя_столбца 2 INT‘
query = 'CREATE TABLE {}(%s)' % columns_string
query = sql.SQL(query).format(sql.Identifier('test_table'))
Если мы проверим запрос:
print(query.as_string(conn))
СОЗДАЙТЕ ТАБЛИЦУ «test_table» (column_name_1 VARCHAR(2), column_name_2 INT)
Мы выполняем это как cur.execute(query)
, и это работает. Не сложное и, вероятно, ненадежное решение, но работает.
Ответ №2:
У меня также было так много проблем с этим аспектом. sql.Identifier
предназначен для двойных кавычек, ну, идентификаторов SQL, которые INTEGER
не TEXT
являются типами данных (, и т.д.). Похоже, что простое использование SQL делает свое дело.
Примечание В вашем коде вы должны иметь заранее определенные columns
кортежи и не предоставлять их определение интерфейсу. Именно поэтому здесь полезны кортежи, поскольку они неизменяемы.
import psycopg2.sql as sql
def create_table( name, columns ):
# name = "mytable"
# columns = (("col1", "TEXT"), ("col2", "INTEGER"), ...)
fields = []
for col in columns:
fields.append( sql.SQL( "{} {}" ).format( sql.Identifier( col[0] ), sql.SQL( col[1] ) ) )
query = sql.SQL( "CREATE TABLE {tbl_name} ( {fields} );" ).format(
tbl_name = sql.Identifier( name ),
fields = sql.SQL( ', ' ).join( fields )
)
print( query.as_string(conn) ) # CREATE TABLE "mytable" ( "col1" TEXT, "col2" INTEGER );
# Get cursor and execute...