SELECT 실행 중...위치..."MySQLdb를 사용하여 입력..."
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')
?
그나저나, 만약 내가 그 역할을 바꾼다면bar
그리고.fooid
, 나는 그것들을 선택하기 위한 코드를 얻을 수 있다.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
실제로, 너무 많은 견적이 주위에 배치되어 있는 것 같습니다.A
그리고.C
.
@Amber님의 코멘트 덕분에 무엇이 잘못되고 있는지 더 잘 알 수 있었습니다.MySQLdb는 매개 변수화된 인수를 변환합니다.['A','C']
로.("'A'","'C'")
.
를 사용하여 파라미터화된 쿼리를 만드는 방법이 있습니까?IN
SQL 구문?아니면 SQL 문자열을 수동으로 구성해야 합니까?
유감스럽게도 쿼리 파라미터를 수동으로 작성해야 합니다.왜냐하면 제가 알기론 빌트인은 없습니다.bind
결속법list
에 대해서IN
휴지기와 유사한 절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)
SQL에서 %s 문자열 목록을 작성하는 데 더 효율적이라고 생각하는 유사한 솔루션을 다음에 제시하겠습니다.
를 사용합니다.
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의 드라이버로 직접 이동하기 때문에 주입은 없습니다.문자열에 원하는 문자를 남길 수 있습니다.문자를 삭제하거나 따옴표로 묶을 필요는 없습니다.
쿼리에 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))
즉, 선형 배열의 모든 매개 변수를 조인한 다음 실행 메서드에 태플로 전달합니다.
이거면 돼요.
myTuple= tuple(myList)
sql="select fooid from foo where bar in "+str(myTuple)
cursor.execute(sql)
주앙이 제안한 것을 할 수 있는 기능을 만들 수 있지 않을까?예를 들어 다음과 같습니다.
def cursor_exec(cursor, query, params):
expansion_params= []
real_params = []
for p in params:
if isinstance(p, (tuple, list)):
real_params.extend(p)
expansion_params.append( ("%s,"*len(p))[:-1] )
else:
real_params.append(p)
expansion_params.append("%s")
real_query = query % expansion_params
cursor.execute(real_query, real_params)
Tornado의 mysql 래퍼와 함께 IN 목록 쿼리를 사용하기 위해 Joang의 솔루션에서 모든 변형을 시도했지만 여전히 "TypeError: not enough arguments for format string" 오류가 발생하고 있습니다.목록 var "*args"에 "*"를 추가하면 효과가 있었습니다.
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
db.query(sql, *args)
Jooo와 satru의 코드를 개선하여 중첩된 반복가능성을 받아들여 올바르게 처리하는 실행으로 커서 작성에 사용할 수 있는 커서 믹스인을 만들 것을 제안합니다.더 、 름 、 이 、 은 、 。경우 Python3을 합니다.str
basestring
.
from MySQLdb.cursors import Cursor
class BetterExecuteMixin(object):
"""
This mixin class provides an implementation of the execute method
that properly handles sequence arguments for use with IN tests.
Examples:
execute('SELECT * FROM foo WHERE id IN (%s) AND type=%s', ([1,2,3], 'bar'))
# Notice that when the sequence is the only argument, you still need
# a surrounding tuple:
execute('SELECT * FROM foo WHERE id IN (%s)', ([1,2,3],))
"""
def execute(self, query, args=None):
if args is not None:
try:
iter(args)
except TypeError:
args = (args,)
else:
if isinstance(args, basestring):
args = (args,)
real_params = []
placeholders = []
for arg in args:
# sequences that we treat as a single argument
if isinstance(arg, basestring):
real_params.append(arg)
placeholders.append('%s')
continue
try:
real_params.extend(arg)
placeholders.append(','.join(['%s']*len(arg)))
except TypeError:
real_params.append(arg)
placeholders.append('%s')
args = real_params
query = query % tuple(placeholders)
return super(BetterExecuteMixin, self).execute(query, args)
class BetterCursor(BetterExecuteMixin, Cursor):
pass
그 후 다음과 같이 사용할 수 있습니다(역호환도 가능합니다).
import MySQLdb
conn = MySQLdb.connect(user='user', passwd='pass', db='dbname', host='host',
cursorclass=BetterCursor)
cursor = conn.cursor()
cursor.execute('SELECT * FROM foo WHERE id IN (%s) AND type=%s', ([1,2,3], 'bar'))
cursor.execute('SELECT * FROM foo WHERE id IN (%s)', ([1,2,3],))
cursor.execute('SELECT * FROM foo WHERE type IN (%s)', (['bar', 'moo'],))
cursor.execute('SELECT * FROM foo WHERE type=%s', 'bar')
cursor.execute('SELECT * FROM foo WHERE type=%s', ('bar',))
매우 심플:
아래 포메이션 ###을 사용합니다.
rules_id = ["9","10"]
sql2 = "SELECT * FROM attendance_rules_staff WHERE id in"+str(tuple(rules_id))
str(tuple(rules_id))
.
왜 이런 경우엔 이것만 안 되는 거죠?
args = ['A', 'C']
sql = 'SELECT fooid FROM foo WHERE bar IN (%s)'
in_p =', '.join(list(map(lambda arg: "'%s'" % arg, args)))
sql = sql % in_p
cursor.execute(sql)
결과는 다음과 같습니다.
SELECT fooid FROM foo WHERE bar IN ('A', 'C')
args는 태플이어야 합니다.
예:
args = ('A','B')
args = ('A',) # in case of single
언급URL : https://stackoverflow.com/questions/4574609/executing-select-where-in-using-mysqldb
'programing' 카테고리의 다른 글
키로 어레이 값 가져오기 (0) | 2022.10.11 |
---|---|
MySQL 테이블, 인덱스 및 데이터 복제 (0) | 2022.10.11 |
HTML5에서 폴리필의 의미는 무엇입니까? (0) | 2022.10.11 |
Chart.js에서 차트의 높이를 설정합니다. (0) | 2022.10.11 |
Axios: 네트워크 오류가 발생하여 요청을 전송하지 않음 (0) | 2022.10.11 |