2016-11-01 35 views
4

所以我重構了一些代碼來使用SQL視圖,而不是在整個地方重複相同的查詢。突然間,一些單元測試開始失敗,查詢沒有所有必需的屬性。SQLite3/python:從VIEW中選擇而不是TABLE時,結果會有所不同

因此,知道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'}] 
+0

使用Python 2.7。這在解析列名時看起來像是一個錯誤。 –

+1

無論如何,當你不使用AS時,不保證列名。 –

+0

可在py3.4和py2.7上重現,linux x86。但是當我將行轉換爲'list'而不是'dict'時,我得到了預期的結果:兩個'['hello','world']' – robyschek

回答

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'}] 

但顯然不能與表的別名空間,因爲y你需要引用他們。也就是說,我認爲在一個表的別名中有空格並且在表別名中沒有空格的情況下可以跳過在select子句中引用表別名。

簡而言之,解決方法是不引用您的表別名。

相關問題