Python pypyodbc如何将变量插入execute语句?

时间:2013-12-01 20:38:41

标签: python odbc quickbooks pypyodbc

我正在使用Python 3.3,pypyodbc 1.2.1和Quickbooks Enterprise 12公司文件访问Flexquarters QODBC版本14.我是编程和python的新手,所以还在学习:)我可以运行查询pypyodbc的例子很好,并产生预期的结果。

注意执行中的硬编码电子邮件地址。这按预期工作:

def get_customer_id(search_col,search_str):
    '''(str,str) --> str

    >>>get_customer_id(email, foo@foo.com)
    80000001-1385782702
    '''
    cur.execute("SELECT listid FROM CUSTOMER WHERE email='foo@foo.com'")
    for row in cur.fetchall():
        for field in row: 
            return field

如果我尝试使用我从pypyodbc文档中读取的参数执行相同的操作,则会抛出错误。我认为引号和参数标记存在问题。

def get_customer_id(search_col,search_str):
    '''(str,str) --> str

    >>>get_customer_id(email, foo@foo.com)
    80000001-1385782702
    '''
    cur.execute("SELECT listid FROM CUSTOMER WHERE email=?",(search_str,))
    for row in cur.fetchall():
        for field in row: 
            return field

试图更加愚蠢?我真的想重用该函数来搜索不同的列。类似的东西:

cur.execute("SELECT listid FROM CUSTOMER WHERE search_str=search_col")

我已经看了一些其他线程,其中大多数似乎只是处理参数,而不是要搜索的列。谁能帮助我学习这个?

PS忘了包含追溯:

Traceback (most recent call last):
  File "C:\Users\Mike\Documents\Projects\qb_sync\quickbooks.py", line 32, in <module>
    print(get_customer_id('email','foo@foo.com'))
  File "C:\Users\Mike\Documents\Projects\qb_sync\quickbooks.py", line 27, in get_customer_id
    cur.execute("SELECT listid FROM CUSTOMER WHERE email=?",[search_str,])
  File "C:\Python\lib\site-packages\pypyodbc.py", line 1457, in execute
    self._BindParams(param_types)
  File "C:\Python\lib\site-packages\pypyodbc.py", line 1420, in _BindParams
    check_success(self, ret)
  File "C:\Python\lib\site-packages\pypyodbc.py", line 982, in check_success
    ctrl_err(SQL_HANDLE_STMT, ODBC_obj.stmt_h, ret, ODBC_obj.ansi)
  File "C:\Python\lib\site-packages\pypyodbc.py", line 960, in ctrl_err
    raise Error(state,err_text)
pypyodbc.Error: ('HY004', '[HY004] [Microsoft][ODBC Driver Manager] SQL data type out of range')
[Finished in 1.7s]

3 个答案:

答案 0 :(得分:3)

我认为使用

cur.execute("""SELECT listid FROM CUSTOMER WHERE ?=?""",[column, email])

不能被数据库引擎接受,而不是pypyodbc或任何其他odbc接口。数据库引擎拒绝接受查询以使用列名参数。

可能你必须尝试这个来重用这个功能:

# First construct your dynamic query for the targeted column
sql = """SELECT listid FROM CUSTOMER WHERE %s=?""" %(column) 

# Then provide the dynamic value for the dynamic query string
cur.execute(sql, (value,))

答案 1 :(得分:1)

Python 3还有str.format()方法,它将对字符串中的{index}项进行字符串替换。如果你有很多值要注入你的字符串,这很有用,如:

  

myStr =“我喜欢{0}和{1},但我不喜欢{2}。”。格式(“苹果”,“香蕉”,“菠菜”)
  myStr的
      “我喜欢苹果和香蕉,但我不喜欢菠菜。”

# First construct your dynamic query for the targeted column
sql = """SELECT listid FROM CUSTOMER WHERE {0}=?""".format(column) 

# Then provide the dynamic value for the dynamic query string
cur.execute(sql, (value,))

值得注意的是,这种替换字符串查询中的值的方法可能会受到sql注入的影响。 更安全的方法是使用参数化存储过程。

答案 2 :(得分:0)

到目前为止我得到了1/2的答案。这适用于一个参数,如果我在调用函数之前格式化字符串;

print(get_custid_email(b'foo@foo.org'))

cur.execute("""SELECT listid FROM CUSTOMER WHERE email=?""",[email])

我仍然无法用列名做同样的事情。

print(get_custid_email(b'email',b'foo@foo.org'))

cur.execute("""SELECT listid FROM CUSTOMER WHERE ?=?""",[column, email])

引发了不同的错误:

Traceback (most recent call last):
  File "C:\Users\Mike\Documents\Projects\qb_sync\quickbooks.py", line 34, in <module>
    print(get_custid_email(b'wendy.lindsay@gmail.com'))
  File "C:\Users\Mike\Documents\Projects\qb_sync\quickbooks.py", line 29, in get_custid_email
    cur.execute("""SELECT listid FROM CUSTOMER WHERE ?=?""",['email',email])
pyodbc.ProgrammingError: ('42S00', '[42S00] [QODBC] Data type of parameter cannot be determined (11023) (SQLPrepare)')