2011-07-28 3 views
1

MySQLdb을 사용하여 텍스트 파일의 많은 데이터를 MySQL 서버로 업로드하고 있습니다. 이것은 수동으로 'as', '123', 12, 23 같은 문자열을 준비하는 경우 잘 작동하지만 문자열과 int를 연결해야하므로이 목록을 생성하는 목록을 반복하는 방법을 알 수는 없습니다.MySQLdb를 사용하여 MySql 서버에 int와 문자열 추가하기

다음과 같이 작동하는 insert 문의 예는 다음과 같습니다

import MySQLdb 

# sample data 
table = 'TestTable' 
header = ['ST', 'CODE', 'BC001', 'BC002', 'BC003'] 
values = [['AA', '1234567', 20, 30, 40], ['BB', '1234567', 20, 30, 40], ['CC', '1234567', 20, 30, 40],['DD', '1234567', 20, 30, 40]] 


# local SQL server on my computer 
db = MySQLdb.connect (host = 'localhost', user = 'root', passwd = '', db = 'test') 
# prepare a cursor object using cursor() method 
cursor = db.cursor() 

# header columns 
sql1 = '(' 
for i in range(len(header)): 
    sql1 += header[i] + ',' 
sql1 = 'INSERT INTO ' + table + sql1[:-1] + ')' 

# now loop through data values and combine with header each time 
for i in range(len(values)): 

    sql2 = '' 
    for j in range(len(values[i])): 
     sql2 += values[i][j] + ','  #error occurs here 

    # structure: sql2 = """ VALUES ('AA', '1234567', 20, 30, 40)""" 
    sql2 = 'VALUES ' + table + sql2[:-1] + ')'  
    sql = sql1 + sql2 

    try: 
     # Execute the SQL command 
     cursor.execute(sql) 
     # Commit your changes in the database 
     db.commit() 
    except: 
     # Rollback in case there is any error 
     db.rollback() 

# disconnect from server 
db.close() 

내가 오류 메시지는 다음과 같습니다

""" INSERT INTO ACS(ST, CODE, BC001, BC002, BC003) 
VALUES ('AK', '1234567', 20, 30, 40)""" 

이 내가 목록에서이 문장을 생성하기 위해 시도하는 방법이다

TypeError: unsupported operand type(s) for +: 'int' and 'str' 

나는 왜 그런 일이 벌어지는 지 이해하지만, 다른 방법을 생각할 수는 없습니다. 문자열을 생성합니다. 이 문자열을 만드는 더 좋은 방법이 있습니까?

Win7 64 비트에서 Python27을 사용하고 있습니다.

+0

미안 내가 구글에 그것을 보니 그런 일이 pymsql으로 없다? 홈페이지 pls에 대한 링크를 제공 할 수 있습니까? –

+0

죄송합니다. 잘못된 패키지 이름을 작성했습니다. 그것은 MySQLdb입니다. 나는 질문을 업데이트 할 것입니다; 미안합니다. – djq

답변

5

MySQLdb는 변수를 수동으로 타입 캐스트하지 않아도 이미이 작업을 수행 할 수 있습니다.

이 방법을 사용 하시겠습니까? MySQLdb는 자동으로 내용을 인용하고 어느 정도 SQL 주입 공격으로부터 당신을 보호하기 때문에. 이는 실용적인 환경에서 정말로 중요하며 전문적인 데이터베이스 작업을 계획하고 있다면 익숙해 져야합니다.

MySQLdb 커서 개체를 사용하면 execute() 명령이 int, 문자열 및 기타 변수를 올바르게 형식화하여 INSERT 문에서 작동합니다. 특수 형식의 형식 문자열을 사용하여이 작업을 수행합니다.

c=db.cursor() 
max_price = 5 
min_price = 1 
c.execute("""SELECT spam, eggs, sausage FROM breakfast 
      WHERE price < %s AND price > %s""", (max_price, min_price)) 

주 두 가지가 : 첫째, 모든 변수는 유형에 관계없이, %s 등이 특별한 형식 문자열로 표현되어야한다. 그것은 단지 그것이 작동하는 방식입니다. 둘째, execute()의 두 번째 매개 변수는 튜플이어야하므로 사용할 변수가 하나만있는 경우 (max_price,)과 같이 입력해야합니다. 괄호 끝에있는 쉼표는 파이썬에 튜플을 알려줍니다.

+0

+1 SQL 주입 보호. – mcstrother

+0

이것은 확실히 더 좋은 방법입니다. 나는 방금이 접근법을 알지 못했다는 것을 위에서 언급했다. 난 그냥 목록을 통과하여 그것을 테스트하고, 그 MySQL은 따옴표 "AA"로 문자열을 표시하는 반면 다른 방법 (그냥 AA로 표시)하지 않는 것으로 나타났습니다. 이것을 막을 수 있습니까? – djq

+0

우리가 여기서 말하는 MySQL 데이터 유형은 무엇입니까? 나는 모든 현이 따옴표로 둘러싸여 져야한다는 인상을 받았다. –

1

values[i][j]str()str(values[i][j])과 같이 간단하게 표시하려고 했습니까? 당신이 더욱를 단순화하기를 원한다면 당신은 또한

sql2 = ','.join([str(x) for x in values[i]]) + ',' 

을 할 수있는 것처럼

는 것 같습니다. (확실하지 후행 쉼표가 필요합니다,하지만 난 당신의 코드에 맞게 포함합니다.)

예 : 한편

>>> my_list = ['abc', 1, 2,3, 'do','re','mi'] 
>>> [str(x) for x in my_list] 
['abc', '1', '2', '3', 'do', 're', 'mi'] 
>>> ','.join([str(x) for x in my_list]) 
'abc,1,2,3,do,re,mi' 

, 당신은 원래 문자열이 포장 된 개체가해야하는 경우 당신이 할 것 같습니다 마지막 쿼리에서 작은 따옴표로, 당신은 아마 제대로 오류를 식별 된 다른 게시물

sql2 = '' 
for x in values[i]: 
    if isinstance(x, basestring): 
     sql2 += "'"+x+"'," 
    else: 
     sql2 += str(x) +"," 
+0

제안 해 주셔서 감사합니다. 나는 따옴표'''''를 세 번 반복 할 수 있어야하고 string 타입의 변수를'''로 묶어야합니다. 그렇지 않으면 데이터베이스가 업데이트되지 않습니다. – djq

+0

죄송합니다. 두 번째 부분을 알아 채고 내 응답을 편집했습니다. 그래도 삼중 따옴표를 사용해야한다는 것에 대해서는 모르겠다. – mcstrother

1

처럼 뭔가 더 복잡한 작업을 수행해야하지만, 더 나은에 귀하의 질문에 대답하지 않았다 문자열 서식을 사용하는 방법.

코드를 읽기가 약간 어렵 기 때문에이 형식이 원하는대로 정확하게 포맷되었는지 확신 할 수 없습니다. 당신이 좋아하는 쿼리를하게 될 겁니다 : 여기

INSERT INTO TestTable (ST,CODE,BC001,BC002,BC003) VALUES ('AA','1234567',20,30,40) 

하는 코드입니다 :

다음
sql = (('INSERT INTO {0} ({1}) VALUES ({2})'.format(table, ','.join(header), 
         ','.join(("'" + v + "'" if isinstance(v, str) 
          else str(v)) for v in val))) for val in values) 

방금 ​​수행

for q in sql: 
    try: 
     # Execute the SQL command 
     cursor.execute(q) 
     # Commit your changes in the database 
     db.commit() 
    except: 
     # Rollback in case there is any error 
     db.rollback() 

그것은 문자열에 따옴표를 추가하고, str.join을 사용하고, str.format.

정말 매개 변수가있는 쿼리를 사용해야합니다.이 쿼리를 사용하면 값을 데이터베이스 커넥터 나 데이터베이스 자체의 문자열에 넣을 수 있습니다.

+0

일반화를 위해 isinstance 호출에서'str' 대신'basestring'을 사용하고 싶을 것입니다. 파이썬 문서 http://docs.python.org/library/stdtypes.html#str.format – mcstrother

+0

아! 더 잘 알지 못했습니다. 매개 변수화 된 쿼리 작성 방법을 읽었습니다. 한 번만 개인용 컴퓨터에서 대량 데이터를 업로드하는 것이므로 보안에 문제가 없습니다. – djq

-1

오류는 MySQLdb와 전혀 관련이 없습니다.

정수와 문자열을 병합하려면 '+'연산자를 사용하고 있습니다. values 배열에 문자열과 정수가 혼합되어 있고 문자열 추가 연산자를 사용하여 문자열과 정수가 혼합되어 있습니다 (예 : mystry = 1+','과 같은 작업).

문제의 해결책은 배열의 항목에 str()을 사용할 수 있습니다. 마찬가지로 :

sql2 += str(values[i][j]) + ','

+0

하지만 수동으로 조각 형식 문자열을 사용하고 있습니다. 오류는 MySQLdb와 관련이 없지만 당신은 깨달을 질문의 내용을 살펴 봤습니다. 그는 그가 사용하고있는 함수에 의해 정확하게 제공되는 행에 값 목록을 삽입하려고합니다. –