2016-07-24 13 views
0

私はpythonとsqliteを使用してスコアリングサーバーを作成していますが、更新を使用するとエラーが発生しました。Python SQLiteの更新エラー

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 
>>> 

スコア表のようになります。ご覧のとおり score table screenshot

、そこFXVCWI列とZSPEF1行があると、その値を変更したいのですが、エラーにはZSPEF1列が存在しないと言います。
UPDATEコマンドは、update_user_score関数でのみエラーが発生します。

なぜこれが私に起こりますか? また、stringの最初の文字がnumberのときにエラーが発生することがあります。このエラーを防ぐ方法はありますか?

は、ここであなたがいない引用で、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

私はあなたの周りに二重引用符が必要だと思います – fodma1

+0

@ fodma1それは私にとってはうまくいきませんでした。 "UPDATE score {0} = {1} WHERE 'USER_ID' = {2}"フォーマット(songID、score、cardID) –

+0

@ LeeM.U。あのようでなく。私は実際のID'を意味していました。 "UPDATEスコア{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)を補間するのも面倒です。その文字列を前に検証するようにしてください。

1曲あたりの列を作成しているように見えます。適切なリレーショナルテーブルの設計についてもう少し詳しくお読みになりたい場合は、ではなく、のデータを列名に格納してください。代わりにuser_song_scores多対多テーブルを使用します。そのテーブルに(USER_ID, SONG_ID, SCORE)タプルが格納されています。これにより、列名を生成する必要がなくなり、指定した曲のスコアをUPDATE user_song_scores SET score=? WHERE USER_ID=? AND SONG_ID=?で更新できます。

+0

ありがとうございました!これは私のために働いた。私は多対多のテーブルについて知りませんでしたので、DBの初心者です。たぶん私は私のコードを書き直す必要があります;) –

関連する問題