2

我正在使用 Python 3.3、pypyodbc 1.2.1 和通过 Flexquarters QODBC 版本 14 访问的 Quickbooks Enterprise 12 公司文件。我是编程和 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]
4

3 回答 3

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,))
于 2013-12-02T07:30:53.730 回答
1

Python 3 还具有 str.format() 方法,该方法将对字符串中的 {index} 项进行字符串替换。如果您有许多值要注入到您的字符串中,这将非常有用,例如:

myStr = "我喜欢 {0} 和 {1},但我不喜欢 {2}。".format("apples","bananas","spinach")
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 注入的影响。更安全的方法是使用参数化存储过程。

于 2017-11-01T16:22:40.017 回答
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)')
于 2013-12-02T05:45:22.897 回答