0

次のコードがあります。

### Write the new userid to the sql database
# Open database connection
db = MySQLdb.connect("sql01.domain1.lan","webuserid","test","webuserid" )
# prepare a cursor object using cursor() method
cursor = db.cursor()



dub_userid = int(userid)
# Check for dublicate of current userid value
sql = "SELECT * FROM webuserid WHERE userid = '"+str(dub_userid)+"'"
try:
        # Execute the SQL command
        cursor.execute(sql)
        # Fetch all the rows in a list of lists.
        results = cursor.fetchone()
        data = cursor.fetchone()
except:
        print "SQL Error: Unable to fetch data"
if data == None:
        print "User doesn't exist - Creating"
else:
        sys.exit("User exists")

# Prepare SQL query to INSERT a record into the database.
sql = """INSERT INTO webuserid(userid)
         VALUES ('"""+userid+"""')"""
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()

変数 userid の文字列値は 00001 です

コードで実行したいのは、データベースに接続し (動作)、ユーザー ID を dub_userid の整数に変換し、結果の値を使用して重複を探すことです。

問題は、コードを実行すると、userid 値が 00001 の場合に次のことが発生することです。

  1. ユーザー ID 1 はデータベースにコミットされます (1 と呼ばれる他のユーザー ID がないため、当然のことです)
  2. 次回の実行では、ユーザー ID 1 が再びデータベースにコミットされます (ユーザー ID 1 が既に存在するため、そうすべきではありません)。
  3. 3 回目の実行では、スクリプトが存在し、「ユーザーが存在します」というメッセージが表示されます。

data と data[1] の両方を試しましたが、何が問題なのかわかりません。

4

2 に答える 2

2

文字列補間を使用したくない場合は、代わりに SQL パラメータを使用してください次に、2 つの行をフェッチしています。本当に必要なのは、行があるかどうかをテストすることだけです。

sql = "SELECT * FROM webuserid WHERE userid = %s"

try:
    # Execute the SQL command
    cursor.execute(sql, (dub_userid,))
    found = cursor.rowcount
except:
    print "SQL Error: Unable to fetch data"
if not found:
    print "User doesn't exist - Creating"
else:
    sys.exit("User exists")

sql = """INSERT INTO webuserid(userid)
         VALUES (%s)"""
try:
    # Execute the SQL command
    cursor.execute(sql, (userid,))
    # Commit your changes in the database
    db.commit()
except:
    #Rollback in case there is any error
    db.rollback()
# disconnect from server
db.close()

これはさらに単純化できます。コンテキストマネージャーとして使用dbして、自動的にコミットするか、失敗した場合にロールバックできます。

with db:
    cursor.execute(sql, (userid,))

db.close()
于 2013-04-07T15:40:15.290 に答える
1

この問題は、Python コードを記述するのではなく、テーブルに UNIQUE 制約を追加することで解決できますし、解決する必要があります。Python コードを記述して制約を適用しようとすると、誰かが他の方法でデータを挿入する可能性がまだあります。制約を追加すると、その制約はデータベース自体によって適用されます。

ALTER TABLE tablename ADD UNIQUE indexname (userid)

この制約を追加した後INSERT、制約に違反した場合、ステートメントは例外を発生させます。cursor.executeを a でラップしてtry...except、違反を処理できます。

テーブルに制約に違反する行がすでにある場合は、

ALTER IGNORE TABLE tablename ADD UNIQUE indexname (userid)

制約を追加し、制約に違反するすべての行削除します (一意のユーザー ID ごとに 1 つの行を残します)。

于 2013-04-07T15:40:02.683 に答える