2017-07-19 60 views
0

這裏有一段我​​的Python代碼,而probe_id是一個字符串:MySQLdb的自動添加'到%s

sql = "select flow_id from t_static_flow where probe_id = %s"                             
cursor = connection.cursor()          
cursor.execute(sql, (probe_id,))         

它運作良好,並且但是當我改變上面的SQL來

sql = "select flow_id from t_static_flow where probe_id = '%s'" 

它給了我這樣的錯誤信息:

(1064,「您的SQL語法錯誤;檢查對應於您的MySQL服務器版本的使用權語法手冊近‘123’‘’在第1行「)

當我添加''圍繞%s時,它失敗。但爲什麼 ?

我打開mysql general_log查看要執行的sql。

2017-07-19T13:21:37.107960Z  85 Query  select flow_id from t_static_flow where probe_id = '123' 

這是我的第一個代碼的效果很好SQL日誌。

,但我認爲在第一個代碼最終SQL應該是:

select flow_id from t_static_flow where probe_id = 123 

它是如何工作的?

我讀了MySQLdb的python代碼。在執行功能:

if args is not None: 
if isinstance(args, dict): 
    query = query % dict((key, db.literal(item)) 
     for key, item in args.iteritems()) 
    else: 
     query = query % tuple([db.literal(item) for item in args]) 

我認爲它不會像@money那樣做額外的工作。

+0

爲什麼你認爲最終查詢應該是:從t_static_flow中選擇flow_id,其中probe_id = 123. probe_id是一個字符串字段,那麼它應該被引號包圍。 – money

+0

但如何解釋,如果我給出了一個錯誤,如果我圍繞在SQL中引用%s這樣sql =「從t_static_flow選擇flow_id其中probe_id ='%s'」? – GuangshengZuo

+0

我認爲cursor.execute(sql,(probe_id,))只是轉義字符串,然後使用「從t_static_flow中選擇flow_id,其中probe_id =%s」來格式化字符串,並且%s不是由引號引起的。 – GuangshengZuo

回答

1

按細節,即使沒有圍繞價值提供了一個單引號,最終查詢看起來像
select flow_id from t_static_flow where probe_id = '123'
價值已經有單引號,所以當你明確添加圍繞價值單引號,這使它像
select flow_id from t_static_flow where probe_id = ''123'' and breaks the query.

+0

「價值已經有單引號」的含義是什麼? probe_id的字符串是123,不包括單引號 – GuangshengZuo

1

我想我找到了答案。首先感謝@錢的幫助。

在MySQLdb的的執行我在問題中提到功能,它採用了字面功能逃串。事實上,文字調用C API來解決這個問題。真正的轉義功能是mysql_real_escape_string。在這個文檔中,我發現這個詞:

嚴格地說,MySQL只需要反斜槓和用於引用查詢字符串的引號字符就會被轉義。

下面是我在_mysql.c找到詞語

string_literal(OBJ) - 轉換對象OBJ到SQL字符串文字。 這意味着,任何特殊的SQL字符都會被轉義,並且在單引號內包含 。

所以它引用mysql_real_esacep_string()API中的字符串並返回。

所以在執行的代碼中,查詢%...替換字符串包含單引號了。

與@money相同。