2016-07-24 3 views
0

python 및 sqlite를 사용하여 점수 서버를 작성하고 있습니다. 업데이트를 사용할 때 오류가 발생했습니다. 보시다시피 score table screenshotPython SQLite 업데이트 오류

,이 FXVCWI 열 및 ZSPEF1 행이며, 그 값을 변경하려면,하지만 오류는 ZSPEF1 열이없는 말합니다 :

Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec 5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from server import * 
>>> db = DB_control() 
>>> db.update_user_score("ZSPEF1", "FXVCWI", 180) 
UPDATE score SET FXVCWI = 180 WHERE USER_ID = ZSPEF1 
Error raised while updating ID ZSPEF1's score to 180. Rolling back DB... 
DB Successfully rolled back 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "server.py", line 102, in update_user_score 
    musica_db.execute(update_score_str) 
sqlite3.OperationalError: no such column: ZSPEF1 
>>> 

점수 표는 다음과 같습니다.
UPDATE 명령은 update_user_score 기능에서만 오류가 발생합니다.

왜 이런 일이 생깁니 까? 또한 문자열의 첫 번째 문자가 숫자 일 때 오류가 발생하는 경우가 있습니다. 이 오류를 방지 할 수있는 방법이 있습니까?

여기가 더 인용으로, SQL 오브젝트 이름으로 열 값을 보간하는 내 코드

#!/usr/bin/env python 
import sqlite3 

musica_db_file = sqlite3.connect("musica.db") 
musica_db = musica_db_file.cursor() 

class DB_control(object): 
    def setupDB(self): 
     #This function should execute only on first run. 
     try: 
      userDB_setupDB_str = "NUM   INTEGER PRIMARY KEY AUTOINCREMENT, " 
      userDB_setupDB_str += "CARD_ID  TEXT NOT NULL UNIQUE, " 
      userDB_setupDB_str += "NAME  TEXT NOT NULL UNIQUE, " 
      userDB_setupDB_str += "PASSWORD TEXT NOT NULL, " 
      userDB_setupDB_str += "ADMIN  INT NOT NULL DEFAULT 0" 

      songDB_setupDB_str = "NUM   INTEGER PRIMARY KEY AUTOINCREMENT, " 
      songDB_setupDB_str += "SONG_ID  INT NOT NULL UNIQUE, " 
      songDB_setupDB_str += "NAME  TEXT NOT NULL UNIQUE, " 
      songDB_setupDB_str += "FINGERPRINT TEXT NOT NULL UNIQUE" 

      scoreDB_setupDB_str = "USER_ID  TEXT NOT NULL UNIQUE" 

      musica_db.execute('CREATE TABLE user({0}) '.format(userDB_setupDB_str)) 
      musica_db.execute('CREATE TABLE song({0}) '.format(songDB_setupDB_str)) 
      musica_db.execute('CREATE TABLE score({0})'.format(scoreDB_setupDB_str)) 
      musica_db_file.commit() 

      self.add_user(randomID(), 'MU_Admin', 'yj809042', admin=True) #Create admin account. 
      self.add_song(randomID(), 'Tutorial', randomID()) #Create tutorial(dummy) song 
      print("DB setuped.") 
     except: 
      print("Error raised while setuping DB") 
      raise 
    def update_user_score(self, cardID, songID, score): 
     try: 
      update_score_str = "UPDATE score SET {0} = {1} WHERE USER_ID = {2}".format(songID, score, cardID) 
      print update_score_str 
      musica_db.execute(update_score_str) 
      musica_db_file.commit() 
      print("User ID {0}'s score is now {1}.".format(cardID, score)) 
     except: 
      print("Error raised while updating ID {0}'s score to {1}. Rolling back DB...".format(cardID, score)) 
      self.rollback_DB() 
      raise 
    def rollback_DB(self): 
     try: 
      musica_db_file.rollback() 
      musica_db_file.commit() 
      print("DB Successfully rolled back") 
     except: 
      print("Error raised while rolling back DB. Critical.") 
      raise 
+0

나는 당신이 user_id 주위에 인용 부호가 필요하다고 생각한다. – fodma1

+0

@ fodma1 그것은 나를 위해 일하지 않았다. "UPDATE score {0} = {1} WHERE 'USER_ID'= {2}". 형식 (songID, score, cardID) –

+0

@ LeeM.U. 그렇게하지 마라. 나는 실제 ID를 의미했다. "UPDATE score {0} = {1} WHERE USER_ID = '{2}'" – fodma1

답변

1

입니다 :

update_score_str = "UPDATE score SET {0} = {1} WHERE USER_ID = {2}".format(songID, score, cardID) 
musica_db.execute(update_score_str) 

는 SQL 에 대한 문자열 보간을 사용하지 마십시오. 대신 바인드 매개 변수를 사용하여

update_score_str = "UPDATE score SET {0} = ? WHERE USER_ID = ?".format(songID) 
musica_db.execute(update_score_str, (score, cardID)) 

cursor.execute() 함수는 SQL 인젝션의 위험을 줄일 수, 인용 적절한 처리됩니다.

SQL 오브젝트 이름 (여기서는 songID)을 보간하는 경우도 마찬가지입니다. 그 문자열의 유효성을 확인하십시오.

노래 당 열을 만드는 것처럼 보입니다. 적절한 관계형 테이블 디자인에 대해 좀 더 읽고 싶은데 이 아니고 데이터를 열 이름에 저장하십시오. user_song_scores many-to-many 테이블 대신에 (USER_ID, SONG_ID, SCORE) 튜플을 저장하여 주어진 노래의 점수를 UPDATE user_song_scores SET score=? WHERE USER_ID=? AND SONG_ID=?으로 업데이트하고 열 이름을 생성하지 않아도됩니다.

+0

감사합니다. 이것은 나를 위해 일했다. 나는 DB에 익숙하지 않았기 때문에 many-to-many 테이블에 대해 알지 못했다. 어쩌면 내가 코드를 다시 작성해야한다;) –