我最近发现一些Access SQL查询有一个错误,我似乎无法追踪。我有一个相当简单的SQL查询,用于从旧应用程序中"管理"的访问数据库中检索数据(即数据已经在数据库中,我无法真正控制其中的内容)。
import pyodbc
MDB = '******.MDB'
DRV = '{Microsoft Access Driver (*.mdb)}'
PWD = ''
con = pyodbc.connect('DRIVER={};DBQ={};PWD={}'.format(DRV, MDB, PWD))
sql = ('SELECT Estim.PartNo, Estim.Descrip, Estim.CustCode, Estim.User_Text1, Estim.Revision, ' +
'Estim.Comments, Routing.PartNo AS RPartNo, Routing.StepNo, Routing.WorkCntr, Routing.VendCode, ' +
'Routing.Descrip AS StepDescrip, Routing.SetupTime, Routing.CycleTime, ' +
'Routing.WorkOrVend, ' +
'Materials.PartNo as MatPartNo, Materials.SubPartNo, Materials.Qty, ' +
'Materials.Unit, Materials.TotalQty, Materials.ItemNo, Materials.Vendor ' +
'FROM (( Estim ' +
'INNER JOIN Routing ON Estim.PartNo = Routing.PartNo ) ' +
'INNER JOIN Materials ON Estim.PartNo = Materials.PartNo )')
if 'PartNo' in kwargs:
key = kwargs['PartNo']
sql = sql + 'WHERE Estim.PartNo=?'
cursor = con.cursor().execute(sql, key)
# use this for debuging only
num = 0
for row in cursor.fetchall():
num += 1
return num
这适用于除PartNo
包含小数点外的所有PartNo
。奇怪的是,当PartNo
包含一个小数点和一个连字符时,我会得到适当的记录。
kwargs['PartNo'] = "100.100-2" # returns 1 record
kwargs['PartNo'] = "200.100" # returns 0 records
当在另一个应用程序中查看时,两个PartNo
都存在,所以我知道应该为这两个查询返回记录。
我的第一个想法是确保kwargs['PartNo']
是一个没有更改的字符串key = str(kwargs['PartNo'])
。
我还试图在'PartNo'
值周围加引号,但没有成功。key = ''' + kwargs['PartNo'] + '''
最后,我试图逃离.
,但没有成功(我意识到这会破坏大多数查询,但我只是试图用一个周期来追踪问题)key = str(kwargs['partNo']).replace('.', '"."')
我知道使用查询参数应该为我处理所有的转义,但在这一点上,我只是想弄清楚发生了什么。对此有什么想法吗?
所以问题不在于查询参数——一切都正常工作。问题出在SQL语句上。我错误地假设——而且从未检查过——Materials
表中有一条记录与PartNo
匹配。
INNER JOIN Materials ON Estim.PartNo = Materials.PartNo
只有在两个表中都找到PartNo
的情况下才会返回一条记录,而在这种特殊情况下则不是。
将其更改为
LEFT OUTER JOIN Materials ON Estim.PartNo = Materials.PartNo
产生预期结果。有关JOIN的信息,请参阅此。https://msdn.microsoft.com/en-us/library/bb243855(v=office.12).aspx
对于print (repr(key))
,烧瓶正确处理上游的夸尔格型
api.add_resource(PartAPI, '/api/v1.0/part/<string:PartNo>'
所以当我在浏览器中运行这个时,我得到了"全长"字符串。当使用python -c .......
在cmd行中运行时,我没有像Gord指出的那样正确处理参数类型,所以它截断了后面的零。我不认为烧瓶部分是相关的,所以我从来没有在最初的问题中添加它。