SQLite3 / python:从VIEW而不是TABLE中选择时结果不同

时间:2016-11-01 14:12:29

标签: python sqlite

所以我重构了一些代码来使用SQL视图,而不是在整个地方重复相同的查询。突然之间,一些单元测试开始失败,消息中的查询没有所有必需的属性。

所以,知道VIEW确实应该返回相同的结构(只需要几个过滤器),这很奇怪。我能够使用以下代码重现它:

#!/usr/bin/env python3

import sqlite3

db = sqlite3.connect(':memory:')
db.row_factory = sqlite3.Row

db.execute('CREATE TABLE foo(id INT PRIMARY KEY, alpha TEXT, beta TEXT)')
db.execute('CREATE VIEW  foo_view AS SELECT * FROM foo')

db.execute("INSERT INTO foo(alpha, beta) VALUES ('hello', 'world')")

foo_res      = [dict(r) for r in db.execute('SELECT "f"."alpha", "f"."beta" FROM "foo"      "f"')]
foo_view_res = [dict(r) for r in db.execute('SELECT "f"."alpha", "f"."beta" FROM "foo_view" "f"')]

print(foo_res)
print(foo_view_res)

运行时,输出如下所示:

[{'alpha': 'hello', 'beta': 'world'}]
[{'f': 'hello'}]

在我看来,那些应该导致完全相同的词典。这是怎么回事?

python3和python2之间也有区别。在python2上运行时,输出如下:

[{'alpha': u'hello', 'beta': u'world'}]
[{'"f"."beta"': u'world', '"f"."alpha"': u'hello'}]

1 个答案:

答案 0 :(得分:0)

是的,这是一个问题。我的目的是解决方法。

问题似乎仅限于引用select子句中的表别名。因此,如果没有这些引号,两个查询都可以在python 3中运行:

>>> [dict(r) for r in db.execute("select f.alpha, f.beta from foo f")]
[{'alpha': 'hello', 'beta': 'world'}]
>>> [dict(r) for r in db.execute("select f.alpha, f.beta from foo_view f")]
[{'f.alpha': 'hello', 'f.beta': 'world'}]

(注意:与表查询不同,视图会对别名产生影响。) 当引号被添加到select子句中的表别名时,事情就会出错:

>>> [dict(r) for r in db.execute("select 'f'.alpha, f.beta from foo_view as f")]
[{'f': 'hello', 'f.beta': 'world'}]

如果您的表名中确实有空格,您可以使用:

>>> [dict(r) for r in db.execute('select f."alpha", f."beta" from foo_view as "f"')]
[{'f."alpha"': 'hello', 'f."beta"': 'world'}]

但显然没有表别名中的空格,因为你需要引用它们。也就是说,我认为在表的别名中包含空格是不好的做法 - 并且表别名中没有空格可以跳过引用select子句中的表别名。

简而言之,解决方法不是引用表别名。

相关问题