從0到1學習node(五)之mysql資料庫的操作
使用node操作mysql資料庫時,需要先安裝mysql模塊:
在引入mysql模塊后,就可以進行資料庫的連接和其他的操作了。
1. 連接資料庫
首先保證本地已經安裝資料庫,並已正常啟動,然後開始進行連接:
執行node test.js后,就會輸出:
連接成功,然後連接關閉。這就說明程序可以正常連接資料庫了,然後就開始進行增刪改查的操作。
2. CURD
比如我們有這樣的一個user表,裡面有4個欄位,其中uid是自增欄位:
uid | username | password | |
1 | meizi | meizi | [email protected] |
2 | test | test | [email protected] |
我們就對這個表進行增刪改查的操作。
Advertisements
mysql中有個query方法可以用來執行任意正確的sql語句,然後在回調函數里給出執行sql語句后的結果。query方法是非同步執行的,若並列書寫多個query方法的話,是不能按照書寫順序依次阻塞式執行的。
2.1 查詢
使用最普遍最多的就是查詢操作了。
輸出的結果:
可以看到,結果集是一個數組,數組中的每條數據都是一個RowDataPacket對象,在使用時,可以像json對象一樣獲取數據,也可以使用JSON.stringify把result轉換為json字元串,但是,result並不是JSON數據。而且,即使結果集中只有一條數據,也是以數組的形式返回的。
輸出即為字元串類型的數據。
Advertisements
2.2 添加
向資料庫中添加數據使用的是INSERT,INSERT語句有兩種形式都可以使用:
第1種,先列好要插入的數據對應的欄位,然後跟上數據(如果要給所有的欄位都插入數據,可以省略欄位不寫,但是數據的書寫順序要跟數據表裡的欄位一一對應):
第2種,可以像update操作一樣書寫,將field與value對應的更緊密:
我更加喜歡第2種方式,這種方式更能看出操作了哪些欄位,看出欄位和數據的對應關係。在node中插入數據:
插入數據后返回的結果是:
affectedRows表示數據表中受影響的行數,數據插入成功則為1,失敗則為0;在主鍵自增的情況下,insertId是數據插入成功后對應的主鍵id,如果主鍵不自增,則insertId為0。
2.3 更新
使用update語句更新數據:
輸出的結果:
可以看到輸出結果的類型與插入數據時輸出結果的類型是一樣的。我們分析一下,執行sql語句后,有3種結果:
成功修改數據: affectedRows:1, changedRows:1
要修改的數據與原數據相同: affectedRows:1, changedRows:0
未找到需要修改的數據: affectedRows:0, changedRows:0
因此可以根據這兩個欄位輸出相應的結果。
2.4 刪除
使用delete語句刪除語句:
輸出的結果:
刪除成功,則affectedRows為1,刪除的數據不存在,則為0。
3. 連接池
資料庫連接是一種有限的,能夠顯著影響到整個應用程序的伸縮性和健壯性的資源,在多用戶的網頁應用程序中體現得尤為突出。
資料庫連接池正是針對這個問題提出來的,它會負責分配、管理和釋放資料庫連接,允許應用程序重複使用一個現有的資料庫連接,而不是重新建立一個連接,釋放空閑時間超過最大允許空閑時間的資料庫連接以避免因為連接未釋放而引起的資料庫連接遺漏。
3.1 創建連接池
使用mysql.createPool()可創建連接池:
getConnection()可以共享一個連接,或管理多個連接。
連接使用完后通過調用connection.release()方法可以將連接返回到連接池中,這個連接可以被其它人重複使用:
可以使用connection.destroy()徹底銷毀連接。
3.2 連接池事件
createPool()方法會返回一個連接池實例對象,這個對象中有一些事件。
連接池中產生新連接時會發送'connection'事件:
3.3 query與getConnection的區別
這兩個方法都能進行操作,那麼這兩者有什麼區別呢?
在pool.getConnection中的connection在其回調函數里是一直的,可以保證這一系列的操作都是在同一個connection中執行的;pool.query則每次執行時可能會在不同的connection中執行,可能會得到意想不到的結果。
比如SQL_CALC_FOUND_ROWS和FOUND_ROWS這需要兩個sql語句完成,是獲取檢索行的數目。
這兩個可能在不同的connection中執行,第2個sql語句返回的就不是上一個sql語句的結果了。
4. sql防注入
sql防注入的關鍵就是不能直接把數據拼接到sql語句中,必須得對數據進行轉義,或者使用提供的方法拼接sql語句。這裡主要有四種方法可以使用。
4.1 使用escape()對參數進行編碼
參數編碼方法有:mysql.escape()/connection.escape()/pool.escape(),這三個方法可以在你需要的時候調用:
對雙引號進行了安全轉義。
escapeId()可以對不信任的表名,欄位名進行轉義。
同時,escape()的編碼規則如下:
Numbers不進行轉換
Booleans轉換為true/false
Date對象轉換為』YYYY-mm-dd HH:ii:ss』字元串
Buffers轉換為hex字元串,如X'0fa5'
Strings進行安全轉義
Arrays轉換為列表,如['a', 'b']會轉換為'a', 'b'
多維數組轉換為組列表,如[['a', 'b'], ['c', 'd']]會轉換為('a', 'b'), ('c','d')
Objects會轉換為key=value鍵值對的形式。嵌套的對象轉換為字元串
undefined/null會轉換為NULL
MySQL不支持NaN/Infinity,並且會觸發MySQL錯誤
4.2 佔位符
可以使用?作為參數佔位符。在使用查詢參數佔位符時,在其內部自動調用connection.escape() 方法對傳入參數進行編碼。
同時,如果執行添加或更新操作時,還可以這樣寫:
資料庫中的表明和欄位名,可以使用??作為佔位符,在拼接完成後會自動添加上``:
4.3 使用mysql.format()轉義參數
不多說,樣例如下:
5. 多語句查詢
出於安全考慮node-mysql默認禁止多語句查詢(可以防止SQL注入),啟用多語句查詢可以將multipleStatements選項設置為true:
啟用后可以在一個query查詢中執行多條語句:
6. 總結
本節只是總結了node對mysql資料庫的各種操作,但如果實際應用起來的話,還遠遠不夠。努力學習中...
上一篇文章: