Python:MySQLdb中sql語句'in'和‘like’要注意的一些問題

    昨天優化了一個Django腳本,因爲我嫌它運行效率太慢,放棄了原有的使用Django的QuerySet API,改用第三方包MySQLdb,雖然用起來不方便(因爲要寫很多sql語句,所以相對於QuerySet API而言使用不是那麼便利),但是效率比較高呀。不過我在使用時還是遇到了一些問題,主要是MySQLdb中,sql語句裏的‘in’和‘like’怎麼讓MySQL數據庫識別。

    安裝比較簡單,使用方法網上也有大量資料,可以在網上去查找。今天主要講講我在工作中遇到到的問題。

Python版本2.7.17,MySQLdb版本1.2.5

(1)中文亂碼。

import MySQLdb
conn = MySQLdb.connect(host='xxx',user='xxxxx,passwd='xxxx',db='xxxx')
cursor = conn.cursor()
sql = """select sum(amount_total),sum(amount_untaxed) from account_invoice where comment ="換美金"   and create_time >= '%s' and create_time <= '%s'"""%(date_begin,date_end)
cursor.execute(sql)
result = cursor.fetchall()

這是我當時查詢數據庫的指令,出現了亂碼,提示latin1編碼失敗,即UnicodeEncodeError: 'latin-1' codec can't encode character,後來我知道Mysql默認是latin1編碼。首先我想到的解決辦法是在文件開頭加上

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

因爲以前出現中文亂碼時,用這種方法解決過,很遺憾,不過這次不管用。然後就查看官方手冊呀,全是英文,雖然看不懂全部,但藉助谷歌翻譯還是能開的懂十之六七,那也足夠了,發現MySQLdb.connect()函數可接受一個可以指定編碼方式的參數charset,將其設置爲utf-8即可,還有一種方法就是在conn=MySQLdb.connetct()後面加如下一句代碼:

conn.set_character_set('utf8')

或者在cursor = conn.cursor()後面加下面三句任意一句。

cursor.execute('SET NAMES utf8;')
cursor.execute('SET CHARACTER SET utf8;')
cursor.execute('SET character_set_connection=utf8;')


(2)“in”中碰到的問題


如果已知‘in’在那個集合裏就好辦了,比如下句:

sql = """select sum(credit) from account_moveline where  journal_id not in (34,18) """

關鍵是不知道那個集合的具體是什麼,是個動態的,不知道集合裏具體有多少元素。


想想平時是怎麼用sql語句的。

select * from table where id in (1,2,3,4)
select * from table where name in ('Jhon','James','Kobe')

這裏要分兩種情況,一個是in後面集合()裏的元素沒有引號,一個是有引號。

對於沒有引號的,表示該字段類型是int型,加入有一個so_id = [one for one in range(1,100)],現在要查詢表table1中id在so_id集合中的記錄呢,這個sql語句怎寫呢?

先開始是這樣寫的

sql = """select * from table1 where id in %s "%(tuple(so_is))
cursor.execute(sql)
result = cursor.fetchall()

是模仿select * from table where id in (1,2,3,4),結果報錯,後來在stackoverflow上找到了解決方法,如下:

so_id_string = ",".join(map(str, so_id))
sql = """select * from table1 where id in (%s) "%(so_id_string)
cursor.execute(sql)
result = cursor.fetchall()

其實最後想想,也不難,還是圍繞這select * from table where id in (1,2,3,4)這種格式來的,將so_id裏的元素變成一個用逗號隔開的字符串


對於有引號的,表明該字段類型是字符串型,得想辦法然集合裏面的元素都帶有引號還是上面例子假設表table1裏有個字段state,是char型,其值是用字符'1’,‘2’等表示此時用上面的辦法就不行了。解決方法如下:

so_strings = ", ".join(map(lambda x:"'%s'"% x,so_id))#加了''引號
sql = """select * from table1 where state in (%s) "%(so_string)
cursor.execute(sql)
result = cursor.fetchall()

可能這個例子不好吧,不知道你們能不能看懂,希望有機會的能自己動手操作下,然後再仔細想想,其實原理不是很難,很好理解,萬變不離其宗!


(3)like

        在Mysql中 like '%123%’在MySQLdb中等價與like '%%123%%',它用一個%對Mysql中的%進行轉義。所以Mysql中 like '123%’在MySQLdb中等價與like '123%%;Mysql中 like '%123’在MySQLdb中等價與like '%%123’。


(4)時間類型

用'%s'進行轉義

"""select * from table where create_time >= '%s' and create_time <= '%s'"""%(date_begin,date_end,)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章