首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >正在执行"SELECT ... WHERE ... IN...“使用MySQLdb

正在执行"SELECT ... WHERE ... IN...“使用MySQLdb
EN

Stack Overflow用户
提问于 2011-01-02 00:04:58
回答 10查看 147.3K关注 0票数 59

我在Python中执行一些SQL时遇到了问题,尽管类似的SQL在mysql命令行中运行得很好。

表格如下所示:

代码语言:javascript
复制
mysql> SELECT * FROM foo;
+-------+-----+
| fooid | bar |
+-------+-----+
|     1 | A   | 
|     2 | B   | 
|     3 | C   | 
|     4 | D   | 
+-------+-----+
4 rows in set (0.00 sec)

我可以从mysql命令行执行以下SQL查询,没有问题:

代码语言:javascript
复制
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)

然而,当我尝试在Python中执行相同的操作时,我没有得到任何行,而我期望得到2行:

代码语言:javascript
复制
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)
# ()

因此,问题是:应该如何修改python代码,以选择bar('A','C')中的那些fooid

顺便说一句,我注意到如果我切换了barfooid的角色,我可以获得代码来成功地选择那些fooid(1,3)中的bar。我不明白为什么一个这样的查询(下面)可以工作,而另一个(上面)不能。

代码语言:javascript
复制
sql='SELECT bar FROM foo WHERE fooid IN %s'
args=[[1,3]]
cursor.execute(sql,args)
data=cursor.fetchall()
print(data)
# (('A',), ('C',))

为了清楚起见,下面是foo表的创建方式:

代码语言:javascript
复制
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

编辑:当我使用mysqld -l /tmp/myquery.log启用常规查询日志时,我看到

代码语言:javascript
复制
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

事实上,看起来围绕AC的引用太多了。

感谢@Amber的评论,我更好地理解了哪里出了问题。MySQLdb将参数化参数['A','C']转换为("'A'","'C'")

有没有一种方法可以使用IN SQL语法进行参数化查询?或者必须手动构造SQL字符串?

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2012-05-02 17:12:32

下面是一个我认为在SQL中构建%s字符串列表更有效的similar solution

直接使用list_of_ids

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注入。

注意,数据(list_of_ids)是作为参数(而不是在查询文本中)直接进入mysql的驱动程序的,所以没有注入。您可以在字符串中保留任何字符,不需要删除或引用字符。

票数 52
EN

Stack Overflow用户

发布于 2011-01-02 00:13:08

不幸的是,您需要手动构造查询参数,因为据我所知,没有内置的bind方法可以将list绑定到IN子句,类似于Hibernate的setParameterList()。但是,您可以使用以下命令来完成相同的操作:

Python 3:

代码语言:javascript
复制
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)

Python 2:

代码语言:javascript
复制
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)
票数 70
EN

Stack Overflow用户

发布于 2011-09-09 18:39:01

如果查询中除了in列表之外还有其他参数,那么JG的答案的以下扩展可能会很有用。

代码语言:javascript
复制
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))

也就是说,连接线性数组中的所有参数,然后将其作为元组传递给execute方法。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4574609

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档