【问题标题】:Psycopg2 string formatting with variable names for type creationPsycopg2 字符串格式化,带有用于创建类型的变量名
【发布时间】:2012-09-28 01:59:34
【问题描述】:

当使用 psycopg2 使用其格式化选项在 postgres 中创建变量类型名称时,由于对象名称的错误字符串格式化而引发错误。是否不允许在查询参数中使用 %s 传入名称?

我写的确实解决了我的问题的代码如下(只是寻找更好的方法来解决这个问题)

cursor.execute("CREATE TYPE {0} AS ENUM %s".format(name), (tuple(set([e.upper() for e in elements])),))

【问题讨论】:

    标签: python postgresql list-comprehension psycopg2


    【解决方案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】:

      如您所料,您不能将表名之类的内容作为查询参数传递。

      它们作为协议级别的绑定参数发送,并且(关键)查询必须可以解析为有效的 SQL,并将它们作为占位符。就好像您要运行 SQL 级别的 PREPARE,然后单独运行 EXECUTE。您必须在准备之前将它们格式化为 SQL 字符串,并使用适当的标识符引用。

      双引号您要替换的标识符,并注意您正在传递的字符串中可能出现的双引号,这可能会过早地结束您的引用序列。这些必须加倍。例如,对于表名 some"table,您可以使用:

       'SELECT * FROM "{0}"'.format('some""table');
      

      SQL 注入是一个非常严重的风险;你必须让你的报价准确正确。最好找到 PostgreSQL quote_ident SQL 函数的客户端等效项。

      请注意,双引号标识符区分大小写。确保在数据库中创建它们时始终使用双引号,不要混合使用带引号和不带引号的标识符。

      【讨论】:

        【解决方案3】:

        我也遇到了这个问题,写了一个简短的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()
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多