使用sqlite3.Row按名称索引结果时行为不一致

3 投票
2 回答
2614 浏览
提问于 2025-04-16 04:39

在我的Python应用程序中,我一直使用sqlite3.Row作为行工厂,这样可以通过名称来索引结果,一直没有问题。最近,我把应用程序迁移到了一个新服务器(代码没有改动),结果发现这种索引方法在新服务器上出现了意外的失败,且是在一个特定的条件下。我找不到任何解释。

这个问题似乎是在新服务器上,当我在选择查询中使用了DISTINCT关键字时发生的:

import sqlite3
conn = sqlite3.connect(':memory:')
conn.row_factory = sqlite3.Row
c = conn.cursor()

c.execute('create table test ([name] text)')
c.execute("insert into test values ('testing')")
conn.commit()

c.execute('select [name] from test')
row = c.fetchone()
print row['name'] # works fine on both machines

c.execute('select distinct [name] from test') # add distinct keyword
row = c.fetchone()
print row['name'] # fails on new server (no item with that key)

正如你所看到的,我可以通过使用内存数据库来隔离这个问题,所以这个问题和我现有的数据没有关系。两台机器都是基于Debian的(旧的:Ubuntu 8.10,新的是Debian 5.0.3),而且两台机器都在运行Python 2.5.2。我相信sqlite3模块是Python安装的核心部分,所以我不知道为什么在Python版本相同的情况下会出现这种微妙的故障。

有没有人有任何想法,或者见过类似的情况?

谢谢,
Chris

2 个回答

0

我遇到了一个不同但类似的问题,搜索“indexerror no item with that key”让我找到了这个问题。在我的情况下,问题出在不同版本的sqlite在使用row_factory = sqlite3.Row模式时,对行的键名处理方式不同。在sqlite 3.24.0版本中,像这样的查询:

select table.col
from table

...会在行字典中创建一个像col这样的键。但在旧版本中,似乎使用的是带有表名的键,比如table.col。提供一个明确的别名或者不使用表名来限定列名可以作为解决方法。例如:

select table.col as "col"
from table

或者:

select col
from table
1

试着加上这一行:

print row.keys()

而不是用“print row['name']”,这样你就能看到在第二种情况下,第一列的实际名称是什么(可能是因为用了“DISTINCT”这个关键词而改变了)。

另外,你也可以在这种情况下用 row[0],但这可能不是你想要的结果。:)

撰写回答