之前用tushare分析股票时,数据库选择了sqlite
,原因很简单,它轻量,甚至不需要安装,python自带。但是今天从sqlite读取数据时,发现了一个很严重的问题:无法查询字符串。折腾了一晚上,终于搞定了。在这里记录一下sqlite的相关查询语法以及问题、解决方案。
查询数值型数据
sqlite的语法和mysql非常类似,因此可以直接使用select
语法进行查询。我们以stock.db
数据库中的limit_data
表为例,查询收盘价为1.81的所有记录:
import sqlite3
conn = sqlite3.connect(r'E:\Finance\stock.db')
cursor = conn.cursor() # 获取一个光标
cursor.execute('SELECT * FROM {0} where close = {1}'.format('limit_data',1.81)) # 执行查询
result = cursor.fetchall() # 获取结果
print(result)
结果返回一个列表
[('600610.SH', '20190102', '*ST毅达', 1.81, 5.23, 0.0, 543.7526, 1.0417, 7081263.0, '09:25:04', '09:25:04', 0, 84.03134, 'U'),
……
]
查询字符型数据
接下来查询trade_date
为20190102的所有记录,查询命令改一下就行,注意trade_date
是string
cursor.execute('SELECT * FROM {0} where trade_data = {1}'.format('limit_data','20190102'))
成功返回数据,看来也是可行的。
[('600399.SH', '20190102', '*ST抚钢', 2.63, 5.2, 0.0, 2024.7509, 0.3159, 16382665.0, '09:25:04', '09:25:04', 0, 100.0, 'U'),
……]
再换一个条件试试,查询一下股票代码ts_code
为600399.SH
的记录。
cursor.execute('SELECT * FROM {0} where ts_code = {1}'.format('limit_data','600399.SH'))
报错:OperationalError: unrecognized token: "600399.SH"
,按理说不应该啊,这条记录明明存在啊。
试试其他string?查询name
为中山金马
的记录。
cursor.execute('SELECT * FROM {0} where name = {1}'.format('limit_data','中山金马'))
依然报错,而且报的错误类型还不一样,OperationalError: no such column: 中山金马
再试一下查询limit
为U
(涨停板)?
cursor.execute('SELECT * FROM {0} where limit = {1}'.format('limit_data','U'))
ok,第三种错误类型出现了,OperationalError: near "limit": syntax error
问题解决
上网查了好久,有人说是原始数据有问题,有人说占位符用错了(他们习惯用?
来表示占位符),还有人说sqlite3的版本太旧,需要更新。
一一试过之后,没有一个能解决这个问题的。我甚至一度下载了mysql
,但终究是太过繁琐而且笨重,所以放弃了安装。
最后试了各种方法,我终于发现:原来还是我写的语法有问题,对于字符串,要用引号把{}
括起来。也就是说,上面的代码应该是这样的:
cursor.execute('SELECT * FROM {0} where ts_code = "{1}"'.format('limit_data','600399.SH'))
cursor.execute('SELECT * FROM {0} where name = "{1}"'.format('limit_data','中山金马'))
对于OperationalError: unrecognized token
和OperationalError: no such column
错误类型,就可以解决了。但是OperationalError: near "limit": syntax error
依然存在,猜测limit
与python或sqlite3内置变量名冲突。(带*
同样报这样的错)
那试试转义吧:
cursor.execute('SELECT * FROM {0} where "{1}" = "{2}"'.format('limit_data',r'limit','U'))
成功返回结果!
总结
和mysql不一样,sqlite的condition
必须要用引号括起来。
如果你碰到OperationalError: unrecognized token
和OperationalError: no such column
报错,很有可能是没有引号的原因。
如果碰到OperationalError: near "limit": syntax error
,则有可能是列名与python(或sqlite3)内置函数名冲突,加个转义即可。
如果你不想费心思考虑各种条件,可以直接用以下语法,无论是条件是字符型还是数值型,无论有没有冲突,都可以完美执行查询。
cursor.execute('SELECT * FROM {0} where "{1}" = "{2}"'.format('table',r'col','condition'))
# 0,1,2分别是表名、列名、条件
更新:in条件查询
在condition
为in ?
时,需要注意两点,一是条件序列必须为tuple
(集合),二是占位符{}
不能用括号括起来。语法如下:
cursor.execute('SELECT * FROM {0} where "{1}" in {2}'.format('limit_data',r'trade_date',tuple(trade_cal)))
版权属于:作者名称
本文链接:https://www.sitstars.com/archives/70/
转载时须注明出处及本声明