2013-04-07 65 views
0

我有下面的代碼:充分利用MySQL的價值和循環遍歷它,如果

### 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() 

變量用戶標識有00001

一個字符串值,我想要的代碼做什麼,是連接到數據庫(工作),將用戶標識轉換爲dub_userid中的整數,然後使用結果值查找dublicate。

問題是,當我運行的代碼,並與00001用戶ID值會發生以下情況:

  1. 用戶ID 1將提交給數據庫(理所應當,因爲沒有所謂的1等用戶標識
  2. 下運行,用戶ID 1將提交給數據庫再次(它不應該,因爲用戶標識1已經存在)
  3. 第三次運行,腳本與存在「用戶存在」消息,因爲它應該。

我已經嘗試了數據和數據[1],但似乎無法弄清楚什麼是錯的。

回答

2

你真的是不是想用字符串插值,用SQL參數代替。接下來,您正在提取兩行行;你真正需要做的是測試是否有任何行:

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() 
+0

非常感謝!這實際上工作! 由於可能的SQL注入,無法使用字符串插值? – MadsRC 2013-04-07 15:49:36

+0

確切地說,SQL參數在正確引用數據方面做得更好,並在需要時提供轉換。 – 2013-04-07 16:03:55

+0

再次感謝,我會查看我的代碼並使用%s代替插值:) – MadsRC 2013-04-07 16:05:19

1

此問題可通過向表中添加UNIQUE約束來解決,而不是通過編寫Python代碼來解決。如果您試圖通過編寫Python代碼來強制實施約束,那麼有人仍然有可能通過其他方法插入數據。如果添加約束,則該約束由數據庫本身執行。

ALTER TABLE tablename ADD UNIQUE indexname (userid) 

添加此約束後,如果違反約束,INSERT語句將引發異常。您可以將cursor.execute包裝在try...except中以處理違規行爲。

如果您的表已經具有違反約束的行,然後

ALTER IGNORE TABLE tablename ADD UNIQUE indexname (userid) 

將添加約束下降中違反約束(留下一排爲每一個獨特USEID)的所有行。

+0

不知道MySQL的能做到這一點。我會去改變我的數據庫。謝謝! – MadsRC 2013-04-07 15:50:49