python 为什么会出现“TypeError:当尝试在参数化SQL查询中使用字符串时,“字符串格式化过程中未转换所有参数”?

bogh5gae  于 2023-04-04  发布在  Python
关注(0)|答案(8)|浏览(165)

我有这个代码:

#! /usr/bin/env python
import MySQLdb as mdb
import sys    

class Test:
    def check(self, search):
        try:
            con = mdb.connect('localhost', 'root', 'password', 'recordsdb');
            cur = con.cursor()
            cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )
            ver = cur.fetchone()            
            print "Output : %s " % ver            
        except mdb.Error, e:          
            print "Error %d: %s" % (e.args[0],e.args[1])
            sys.exit(1)            
        finally:    
            if con:    
                con.close()

test = Test()
test.check("test")

但我得到一个错误,如:

Traceback (most recent call last):
  File "./lookup", line 27, in <module>
    test.check("test")
  File "./lookup", line 11, in creep
    cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )
  File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 187, in execute
    query = query % tuple([db.literal(item) for item in args])
TypeError: not all arguments converted during string formatting

什么是错误的,我如何修复它?
同样的问题发生在sqlitem中,报告方式不同;详情请参见sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 74 supplied

r55awzrz

r55awzrz1#

而不是这个:

cur.execute( "SELECT * FROM records WHERE email LIKE '%s'", search )

试试这个:

cur.execute( "SELECT * FROM records WHERE email LIKE %s", [search] )

参见MySQLdb文档。理由是execute的第二个参数表示要转换的对象的列表,因为在参数化查询中可以有任意数量的对象。在本例中,您只有一个对象,但它仍然需要是可迭代的(元组而不是列表也很好)。

fae0ux8s

fae0ux8s2#

您可以尝试以下代码:

cur.execute( "SELECT * FROM records WHERE email LIKE %s", (search,) )

您可以看到the documentation

svgewumm

svgewumm3#

“%”关键字非常危险,因为它是“SQL注入攻击”的主要原因。
所以你只是用这个代码。

cursor.execute("select * from table where example=%s", (example,))

t = (example,)
cursor.execute("select * from table where example=%s", t)

如果您想尝试插入到表中,请尝试以下操作。

name = 'ksg'
age = 19
sex = 'male'
t  = (name, age, sex)
cursor.execute("insert into table values(%s,%d,%s)", t)
vc6uscn9

vc6uscn94#

cur.execute( "SELECT * FROM records WHERE email LIKE %s", (search,) )

我不知道为什么,但这对我很有效。而不是使用'%s'

h6my8fg2

h6my8fg25#

@kevinsa5的公认答案是正确的,但你可能会想“我发誓这段代码 * 曾经 * 工作,现在它不工作了,”你是对的。
MySQLdb库在1.2.3和1.2.5之间有一个API更改。1.2.3版本支持

cursor.execute("SELECT * FROM foo WHERE bar = %s", 'baz')

但是1.2.5版本需要

cursor.execute("SELECT * FROM foo WHERE bar = %s", ['baz'])

我在更新日志中找不到更改,可能之前的行为被认为是一个错误。
Ubuntu 14.04版本库有python-mysqldb 1.2.3,但Ubuntu 16.04及更高版本有python-mysqldb 1.3.7+。
如果您正在处理需要旧行为的遗留代码库,但您的平台是较新的Ubuntu,请从PyPI安装MySQLdb:

$ pip install MySQL-python==1.2.3
vdgimpew

vdgimpew6#

我不明白前两个答案。我想它们一定是版本相关的。我不能在MySQLdb 1.2.3上重现它们,它是Ubuntu 14.04LTS附带的。让我们试试它们。首先,我们验证MySQL不接受双撇号:

mysql> select * from methods limit 1;
+----------+--------------------+------------+
| MethodID | MethodDescription  | MethodLink |
+----------+--------------------+------------+
|       32 | Autonomous Sensing | NULL       |
+----------+--------------------+------------+
1 row in set (0.01 sec)

mysql> select * from methods where MethodID = ''32'';
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '9999'' ' at line 1

没有。让我们试试Mandatory发布的使用/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py内部的查询构造函数的示例,其中我打开“con”作为到数据库的连接。

>>> search = "test"
>>> "SELECT * FROM records WHERE email LIKE '%s'" % con.literal(search)
"SELECT * FROM records WHERE email LIKE ''test''"
>>>

不,双撇号会导致它失败。让我们试试Mike Graham的第一条评论,他建议去掉引用%s的撇号:

>>> "SELECT * FROM records WHERE email LIKE %s" % con.literal(search)
"SELECT * FROM records WHERE email LIKE 'test'"
>>>

是的,这是可行的,但是Mike的第二条注解和文档说要执行的参数(由con.literal处理)必须是一个元组(search,)或一个列表[search]
最好的答案是ksg97031。

nue99wik

nue99wik7#

根据PEP8,我更喜欢以这种方式执行SQL:

cur = con.cursor()
# There is no need to add single-quota to the surrounding of `%s`,
# because the MySQLdb precompile the sql according to the scheme type
# of each argument in the arguments list.
sql = "SELECT * FROM records WHERE email LIKE %s;"
args = [search, ]
cur.execute(sql, args)

通过这种方式,您将认识到execute方法的第二个参数args必须是参数列表。
希望这个能帮到你。

4sup72z8

4sup72z88#

我在执行SELECT * FROM table;时遇到此错误,我将错误追溯到cursor.py第195行。

if args is not None:
        if isinstance(args, dict):
            nargs = {}
            for key, item in args.items():
                if isinstance(key, unicode):
                    key = key.encode(db.encoding)
                nargs[key] = db.literal(item)
            args = nargs
        else:
            args = tuple(map(db.literal, args))
        try:
            query = query % args
        except TypeError as m:
            raise ProgrammingError(str(m))

考虑到我正在输入任何额外的参数,我摆脱了所有的“if args ...”分支。现在它可以工作了。

相关问题