簡體   English   中英

Python MySQLdb:創建表時出現語法錯誤

[英]Python MySQLdb: Syntax Error when create table

代碼非常簡單,我直接從控制台運行它,同時, spider.table_name ='crawler'

import MySQLdb
import scrapy

print (spider.table_name)  # >> 'crawler'

db = MySQLdb.connect(........)
db.set_character_set('utf8')
mysql = db.cursor()

sql = "CREATE TABLE %s like r_template;"
mysql.execute(sql, (spider.table_name, ))
db.commit()

但是我得到了語法錯誤:

ProgrammingError: (1064, "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''crawler' like r_template' at line 1")

似乎正在執行的實際sql語句是:

CREATE TABLE 'crawler' like r_template

單引號“”如何產生? 如何防止它發生?

然后,我以更簡單的方式嘗試:

mysql.execute(sql, ('crawler', ))
mysql.execute("CREATE TABLE %s like r_template", ('crawler', ))

錯誤仍然發生。

您不小心打開了一個神秘而冒險的世界的大門。 我的建議是:看前不要關上那扇門。

問題是您試圖在“左側 ”傳遞占位符的參數,但是與MySQL的接口僅在“ 右側 ”起作用。 占位符用於 ,而不用於字段名稱

膚淺的解釋

讓我從另一個例子開始。

編寫以下內容是合法的:

where field = %s

並且如果變量是字符串,則符合PEP 249的接口將正確解釋它:將其視為“用引號引起來”(盡管不是它的作用,否則它將為SQL注入打開大門;但是那會說明這一點)。

那是在平等的右邊

但是,如果您寫:

where %s = 5

的值為'my_field',則它將不起作用,因為它位於左側 這不是界面的一部分。

就像您說的那樣,如果應用相同的邏輯,它將“在引號周圍”,因此您將獲得:

where 'my_field' = 5

這顯然是沒有意義的,因為您會在不期望的地方得到報價(警告:同樣,這不是發生的事情,但它說明了要點)。 它行不通,但是如果您遵循自己的邏輯,這些引號就是您應該得到的。 存在矛盾,因此某些地方顯然是錯誤的。

可是等等!

更深入的解釋

重要的是要了解,使用PEP 249接口時,占位符的參數不會轉換為字符串,然后放入字符串查詢。 它們被翻譯成它們的等價物(int等)並在較低的層次上處理(我想是在解析樹或類似的結構內)。

已經指定了將參數轉換為值的機制 它不是為變量標識符 (例如字段表)設計的 (這是更高級的用例)。

說“標識符是變量”是一個很高級的想法……我將帶您進入高級編程的美好世界。

可以將PEP249擴展為這樣做嗎? 從理論上講是的,但這不是一個開放和封閉的問題。

同時,您只剩下一個選擇:在將字符串查詢提供給SQL引擎之前先對其進行插值。

sql = "CREATE TABLE %s like r_template;" % 'crawler'

我可以想象你周圍的人為之驚駭( 不要打開那扇門! )。 但是據我所知,如果您確實想擁有一個可變的表名,那就是您必須要做的。

在這一點上,您可能想問自己, 為什么要有一個可變的表名 您是否以此作為其他方法的懶惰替代方法? 在那種情況下, 我會回到人跡罕至的地方,而忘記使表或字段可變。

但是,我看到了兩個變量表或字段完全合法的用例:用於數據庫管理或用於構建數據庫框架

如果是這種情況, 請小心使用字符串插值 ,以避免意外的SQL注入。 您將不得不處理空格,特殊字符等各種不同的問題; 好的做法是“引用”您的字段或表名,例如在標准MySQL中:

桌子重音

而使用ANSI引用:

“桌子重音”

(正如你看到的,你不是那么遙遠!)

也要小心剝離可能使解釋器無法使用的內容,例如分號。

無論如何,如果要這樣做,您將需要在海岸看不見的地方導航,直奔日落。 您正在英雄走到左邊的起點上 只要您接受將沒有救生員來救援,您將享受冒險

使用.format代替%s,這樣可以避免查詢中的單引號。 例如:

my_sql_query = "CREATE TABLE {}".format(table_name)
mysql.execute(my_sql_query)

那應該工作:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM