使用MySQLdb执行“select…where…in…”

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (103)

我在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)

我可以从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)

但是,当我试图在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)
# ()

所以问题是:应该如何修改python代码以选择fooid在哪里bar('A','C')?

顺便说一下,我注意到如果我把barfooid,我可以获得选择这些代码的代码bar在哪里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',))

我要说的是,这就是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

当我启用通用查询日志时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

事实上,似乎有太多的引号被放在了周围。AC...

MySQLdb转换参数化参数。['A','C']("'A'","'C'")...

是否有一种方法可以使用INSQL语法?还是必须手动构造SQL字符串?

提问于
用户回答回答于

这里有一个相似解我认为在SQL中构建%s字符串列表时效率更高:

使用list_of_ids直接: 格式_字符串=‘,’.连接(‘%s’*Len(名单)_成_(ID)cursor.Execute(“从foo.bar中删除Baz in(%s)”%格式_字符串、元组(列表)_成_) 这样,就可以避免引用自己的话,并避免各种SQL注入。 请注意,数据(list_of_ids)直接转到MySQL的驱动程序,作为参数(而不是在查询文本中),因此不需要注入。可以在字符串中保留您想要的任何字符,不需要删除或引用字符。

用户回答回答于

不幸的是,您需要手动构造查询参数,因为据我所知,没有内置。bind绑定a的方法。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)

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)

扫码关注云+社区