使用psycopg2的内置格式创建动态类型的表

时间:2019-06-12 22:05:24

标签: python sql psycopg2

我正在使用Python项目与PostgreSQL数据仓库进行交互,并且正在使用psycopg2 API。我正在寻找创建动态类型的表。

例如:我希望能够执行以下代码:

from psycopg2 import connect, sql

connection = connect(host="host", port="port", database="database", user="user", password="pw")

def create_table(tbl_name, col_name, col_type):
    query = sql.SQL("CREATE TABLE {} ({} {})".format(sql.Identifier(tbl_name), sql.Identifier(col_name), sql.Identifier(column_type)))
    connection.execute(query)

create_table('animals', 'name', 'VARCHAR')

,最后得到一个名为“ animals”的表,该表包含类型为VARCHAR的“名称”列。但是,当我尝试运行此命令时,出现错误:“类型“ VARCHAR”不存在”。我假设psycopg2的内置格式化程序在不应有VARCHAR类型时将双引号引起来。通常,我自己会解决这个问题,但是文档非常明确指出,永远不要使用Python字符串连接,以免担心SQL注入攻击。安全性是该项目的关注点,因此我想知道是否可以使用pyscopg2以这种方式创建动态类型的表,如果不能,是否存在可以安全地执行此操作的第三方API。谢谢!

丹尼

1 个答案:

答案 0 :(得分:1)

我在这方面也遇到了很多麻烦。 sql.Identifier 用于数据类型(INTEGERTEXT 等)not 的双引号 SQL 标识符。看起来只是简单的 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...