【问题标题】:How can I reference columns by their names in python calling SQLite?如何在 python 调用 SQLite 中通过名称引用列?
【发布时间】:2010-10-09 06:46:06
【问题描述】:

我有一些代码一直用于查询 MySQL,我希望将它与 SQLite 一起使用。我真正的希望是这不会涉及对代码进行太多更改。不幸的是,以下代码不适用于 SQLite:

cursor.execute(query)

rows = cursor.fetchall()

data = []
for row in rows
  data.append(row["column_name"])

这会产生以下错误:

 TypeError: tuple indices must be integers

而如果我将引用更改为使用列号,它可以正常工作:

  data.append(row[1])

我能否以可以通过名称引用列的方式执行查询?

【问题讨论】:

    标签: python sqlite


    【解决方案1】:

    自从提出问题并得到回答以来的五年中,出现了一个非常简单的解决方案。任何新代码都可以简单地用行工厂包装连接对象。代码示例:

    import sqlite3
    
    conn = sqlite3.connect('./someFile')
    conn.row_factory = sqlite3.Row        // Here's the magic!
    
    cursor = conn.execute("SELECT name, age FROM someTable")
    for row in cursor:
        print(row['name'])
    

    这里有一些fine docs。尽情享受吧!

    【讨论】:

    • 在此答案之前 2 年发布了相同的答案。
    【解决方案2】:

    要按名称访问列,请使用 Connection 实例的 row_factory 属性。它允许您设置一个函数,该函数接受参数cursorrow,并返回您想要的任何内容。 pysqlite 有一些内置功能,即sqlite3.Row,它可以满足您的要求。

    【讨论】:

    【解决方案3】:

    我不确定这是否是最佳方法,但这是我通常使用 DB-API 2 兼容模块检索记录集的方法:

    cursor.execute("""SELECT foo, bar, baz, quux FROM table WHERE id = %s;""", 
                      (interesting_record_id,))
    
    for foo, bar, baz, quux in cursor.fetchall():
        frobnicate(foo + bar, baz * quux)
    

    查询格式化方法是 DB-API 标准之一,但恰好是 Psycopg2 的首选方法;其他 DB-API 适配器可能会建议使用不同的约定。

    编写这样的查询,其中隐式元组解包用于处理结果集,通常对我来说比试图担心将 Python 变量名与 SQL 列名匹配(我通常只用它来删除前缀)更有效,然后仅当我使用列名的子集时,前缀不再有助于澄清事情),并且比记住数字列 ID 好得多

    这种风格还可以帮助您避免SELECT * FROM table...,这对于除了最简单的表和查询之外的任何东西来说都是一场维护灾难。

    所以,不完全是您所要求的答案,但可能仍然很有启发性。

    【讨论】:

    • 其实这样就完美了!谢谢。
    • 对不起:应该更仔细地检查。这不太行。在 SQLite 中,foo 最终类似于 (123,) 而在 MySQL 中,它最终成为 ('foo': 123)
    • 得到这样的结果让我想知道您的 MySQL 模块是否符合 DB-API 2.0 ......如果不是,尝试替换不同的数据库模块将会很糟糕。您使用的是哪个 MySQL 模块?
    • 我正在使用 MySQLdb...我不知道它是否符合 DB-API 2.0...
    • 不知何故你得到了字典而不是通常的元组。 MySQLdb 文档建议您使用 DictCursor 或其近亲之一,而不是普通游标。如果您想以标准方式获得此行为,Richard 关于使用 row_factory 的建议可能是最好的。
    【解决方案4】:

    这可以通过在“连接”语句后添加一行来完成:

    conn.row_factory = sqlite3.Row
    

    在此处查看文档: http://docs.python.org/library/sqlite3.html#accessing-columns-by-name-instead-of-by-index

    【讨论】:

      【解决方案5】:

      kushal 对this forum 的回答很好:

      使用字典光标:

      import MySQLdb.cursors
      
      .
      .
      .
      cursor = db.cursor (MySQLdb.cursors.DictCursor)
      cursor.execute (query)
      rows = cursor.fetchall ()
      
      for row in rows:
      print row['employee_id'] 
      

      请注意,列名区分大小写。

      【讨论】:

      • 很遗憾,这个答案是针对错误的问题(sqlite 而不是 mysql),因为它完美地回答了我的问题。
      【解决方案6】:

      SQLite API 支持 cursor.description,因此您可以轻松地这样做

      headers = {}
      for record in cursor.fetchall():
          if not headers:
              headers = dict((desc[0], idx) for idx,desc in cursor.description))
          data.append(record[headers['column_name']])
      

      有点啰嗦,但可以完成工作。我注意到他们甚至在 dict_factory 下的 factory.py 文件中有它。

      【讨论】:

        【解决方案7】:

        使用光标描述,像这样:

        rows = c.fetchall()
        for row in rows:
            for col_i, col in enumerate(row):   
                print("Attribute: {0:30} Value: {1}".format(c.description[col_i][0],col))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-26
          • 1970-01-01
          • 1970-01-01
          • 2019-11-27
          • 1970-01-01
          • 2017-10-09
          相关资源
          最近更新 更多