当使用psycopg2使用格式化选项传递变量类型名称以在postgres中创建时,对于对象名称的错误字符串格式化会抛出错误。是否不允许在查询参数中使用%s传递名称?
我写的代码确实解决了我的问题如下(只是寻找更好的解决方法)
cursor.execute("CREATE TYPE {0} AS ENUM %s".format(name), (tuple(set([e.upper() for e in elements])),))
答案 0 :(得分:1)
(2)与PostgreSQL完全无关,也许可以编辑出这个问题并将其发布在一个新问题中?我会回答(1)。
正如您所猜测的那样,您无法将表名等内容作为查询参数传递。
它们作为协议级绑定参数发送,并且(严格地)查询必须可解析为有效的SQL,并将它们作为占位符。就好像你要运行SQL级PREPARE
然后分开EXECUTE
一样。在准备之前,必须使用适当的标识符引用将它们格式化为SQL字符串。
双引号您要替换的标识符,并注意您传递的字符串中可能的双引号,这可能过早地结束您的引用序列。这些必须加倍。例如,对于表名some"table
,您将使用:
'SELECT * FROM "{0}"'.format('some""table');
SQL注入是一个非常严重的风险;你必须正确地引用 。理想情况下,找到PostgreSQL quote_ident
SQL函数的客户端等效项。
请注意,双引号标识符区分大小写。确保在数据库中使用相同的大小写创建它们,始终使用双引号,不要混合使用带引号和不带引号的标识符。
答案 1 :(得分:1)
你实际上不应该对你的查询进行python格式化,而是让 psycopg2 来做。以下是制作它的方法:http://initd.org/psycopg/docs/usage.html#passing-parameters-to-sql-queries即:
cur.execute("INSERT INTO numbers VALUES (%s)", (42,))
从2.7版本开始,psycopg2.sql
模块提供了一些高级格式化功能:http://initd.org/psycopg/docs/sql.html
答案 2 :(得分:0)
我也遇到了这个问题并编写了一个简短的blog post,其中包含使用字符串格式化与远程数据库的连接,但是这个问题和我的解决方案适用于需要将变量传递给SQL命令的任何情况。
以下是我解决此问题的方法:
import psycopg2 as db
import sys
my_host = 'ec2-190-111-829-829.compute-1.amazonaws.com'
my_dbname = 'myDBNameGoesHere'
my_user = 'myUsernameGoesHere'
my_password = 'myPasswordGoesHere'
remote_connection_str = 'host={0} dbname={1} user={2} password={3}'.format(my_host, my_dbname, my_user, my_password)
if __name__ == '__main__':
try:
remote_connection = db.connect(remote_connection_str)
cursor = remote_connection.cursor()
cursor.execute('SELECT version()')
version = cursor.fetchone()
print "\n"
print "Successful connection to database."
print "Database information:\n", version
print "\n"
except db.DatabaseError, e:
print 'Error %s' % e
sys.exit(1)
finally:
if remote_connection:
remote_connection.close()