我在Python中执行某些SQL时遇到问题,尽管类似的SQL在mysql
命令行中工作正常.
该表如下所示:
mysql> SELECT * FROM foo;
+-------+-----+
| fooid | bar |
+-------+-----+
| 1 | A |
| 2 | B |
| 3 | C |
| 4 | D |
+-------+-----+
4 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我可以从mysql命令行执行以下SQL查询,没有问题:
mysql> SELECT fooid FROM foo WHERE bar IN ('A','C');
SELECT fooid FROM foo WHERE bar IN ('A','C');
+-------+
| fooid |
+-------+
| 1 |
| 3 |
+-------+
2 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试在Python中执行相同操作时,我没有获得任何行,而我期望有2行:
import MySQLdb
import config
connection=MySQLdb.connect(
host=config.HOST,user=config.USER,passwd=config.PASS,db='test')
cursor=connection.cursor()
sql='SELECT fooid FROM foo WHERE bar IN %s'
args=[['A','C']]
cursor.execute(sql,args)
data=cursor.fetchall()
print(data)
# ()
Run Code Online (Sandbox Code Playgroud)
所以,问题是:应该如何Python代码进行修改,以选择那些fooid
S其中bar
是('A','C')
?
顺便说一句,我注意到,如果我切换的角色bar
和fooid
,我可以得到代码选择那些bar
S其中fooid
是(1,3)
成功的.我不明白为什么一个这样的查询(下面)工作,而另一个(上面)没有.
sql='SELECT bar FROM foo WHERE fooid IN %s'
args=[[1,3]]
cursor.execute(sql,args)
data=cursor.fetchall()
print(data)
# (('A',), ('C',))
Run Code Online (Sandbox Code Playgroud)
而且为了绝对清楚,这就是foo
表格的创建方式:
mysql> DROP TABLE IF EXISTS foo;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE `foo` (
`fooid` int(11) NOT NULL AUTO_INCREMENT,
`bar` varchar(10) NOT NULL,
PRIMARY KEY (`fooid`));
Query OK, 0 rows affected (0.01 sec)
mysql> INSERT into foo (bar) values ('A'),('B'),('C'),('D');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
Run Code Online (Sandbox Code Playgroud)
编辑:当我启用常规查询日志时,mysqld -l /tmp/myquery.log
我看到了
mysqld, Version: 5.1.37-1ubuntu5.5-log ((Ubuntu)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
110101 11:45:41 1 Connect unutbu@localhost on test
1 Query set autocommit=0
1 Query SELECT fooid FROM foo WHERE bar IN ("'A'", "'C'")
1 Query SELECT bar FROM foo WHERE fooid IN ('1', '3')
1 Quit
Run Code Online (Sandbox Code Playgroud)
事实上,看起来有太多的报价被放置在A
和周围C
.
感谢@ Amber的评论,我更清楚地知道出了什么问题.MySQLdb将参数化参数转换['A','C']
为("'A'","'C'")
.
有没有办法使用IN
SQL语法进行参数化查询?或者必须手动构造SQL字符串?
Joã*_*lva 67
不幸的是,你需要手动构造查询参数,因为据我所知,目前还没有内置bind
的结合的方法list
,以一个IN
条款,类似于Hibernate的setParameterList()
.但是,您可以通过以下方式完成相同的操作:
Python 3:
args=['A', 'C']
sql='SELECT fooid FROM foo WHERE bar IN (%s)'
in_p=', '.join(list(map(lambda x: '%s', args)))
sql = sql % in_p
cursor.execute(sql, args)
Run Code Online (Sandbox Code Playgroud)
Python 2:
args=['A', 'C']
sql='SELECT fooid FROM foo WHERE bar IN (%s)'
in_p=', '.join(map(lambda x: '%s', args))
sql = sql % in_p
cursor.execute(sql, args)
Run Code Online (Sandbox Code Playgroud)
小智 43
这是一个类似的解决方案,我认为在SQL中构建%s字符串列表更有效:
list_of_ids
直接使用:Run Code Online (Sandbox Code Playgroud)format_strings = ','.join(['%s'] * len(list_of_ids)) cursor.execute("DELETE FROM foo.bar WHERE baz IN (%s)" % format_strings, tuple(list_of_ids))
这样你就可以避免引用自己,并避免各种sql注入.
请注意,data(
list_of_ids
)直接作为参数(不在查询文本中)直接转到mysql的驱动程序,因此没有注入.你可以在字符串中留下你想要的任何字符,不需要删除或引用字符.
小智 10
如果查询中有其他参数,超出IN列表,那么JG答案的以下扩展可能会有用.
ids = [1, 5, 7, 213]
sql = "select * from person where type=%s and id in (%s)"
in_ids = ', '.join(map(lambda x: '%s', ids))
sql = sql % ('%s', in_ids)
params = []
params.append(type)
params.extend(ids)
cursor.execute(sql, tuple(params))
Run Code Online (Sandbox Code Playgroud)
也就是说,将所有参数连接在一个线性数组中,然后将其作为元组传递给execute方法.
小智 5
这对我有用:
myTuple= tuple(myList)
sql="select fooid from foo where bar in "+str(myTuple)
cursor.execute(sql)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
137404 次 |
最近记录: |