Node.js調用mysql的存儲過程


例子僅在windows下測試通過,沒有放在linux下測試。如有問題,可以電郵給我~

1、安裝node.js、mysql,此處略(自行搜索吧)…;

2、創建一個名為test的數據庫,然后建一張名為user_info的表(僅供測試)…

這里假定mysql使用的用戶名為root,密碼為123456

相應的mysql如下:

/**
* 創建名為test的數據庫
*/
DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
 

/**
* 創建user_info表
*/
DROP TABLE IF EXISTS `user_info`;

CREATE TABLE `user_info` (
`userId` int(10) NOT NULL AUTO_INCREMENT,
`userName` varchar(20) DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

/**
* 插入三條記錄
*/
INSERT INTO user_info VALUES (NULL, '張一'), (NULL, '張二'), (NULL, '張三');


 

3、創建存儲過程(寫的很冗余,故意的… 正好學習一下語法>_<);

DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`proc_simple`$$
CREATE PROCEDURE proc_simple(IN uid INT(10), OUT uName VARCHAR(2), OUT totalCount INT)
BEGIN

DECLARE str_name VARCHAR(20);

SET @str_name = '';
SET totalCount = 0;
SELECT COUNT(1),userName INTO totalCount,@str_name FROM user_info WHERE userId = uid;
SET uName = @str_name;
SELECT uName, totalCount;

END$$
DELIMITER ;
 
4、寫程序進行調用(假定存為名為sql.js的文件);
/**
* Created with JetBrains WebStorm.
* User: Meteoric_cry
* Date: 12-12-28
* Time: 上午00:18
* To change this template use File | Settings | File Templates.
*/
var mysql = require('mysql');

var connection = mysql.createConnection({
host : 'localhost',
port : 3306,
user : 'root',
password : '123456',
database : 'test',
charset : 'UTF8_GENERAL_CI',
debug : false
});

connection.connect();

connection.query('CALL proc_simple(1, @a, @b);', function(err, rows, fields) {
if (err) {
throw err;
}

var results = rows[0];
var row = results[0];
console.log("userName:",row.uName, "  count:", row.totalCount);
});

connection.end();
 
5、運行示例程序;
 

本文參考鏈接:

mysql 存儲程序和函數

mysql(procedure)

node-mysql

 

 

/***************************************************************/

如果對mysql的行記錄鎖定、表鎖定,有興趣想了解更多,可以繼續閱讀(有空准備寫個復雜點的應用,所以需要了解一些這方面的知識,下面的文字摘抄自SELECT FOR UPDATE):

舉個例子: 假設商品表單products 內有一個存放商品數量的quantity ,在訂單成立之前必須先確定quantity 商品數量是否足夠(quantity>0) ,然后才把數量更新為1。
不安全的做法:
SELECT quantity FROM products WHERE id=3;UPDATE products SET quantity = 1 WHERE id=3;
為什么不安全呢?
少量的狀況下或許不會有問題,但是大量的數據存取「鐵定」會出問題。
如果我們需要在quantity>0 的情況下才能扣庫存,假設程序在第一行SELECT 讀到的quantity 是2 ,看起來數字沒有錯,但是當MySQL 正准備要UPDATE 的時候,可能已經有人把庫存扣成0 了,但是程序卻渾然不知,將錯就錯的UPDATE 下去了。
因此必須透過的事務機制來確保讀取及提交的數據都是正確的。


於是我們在MySQL 就可以這樣測試: (注1)
SET AUTOCOMMIT=0;BEGIN WORK;SELECT quantity FROM products WHERE id=3 FOR UPDATE;

此時products 數據中id=3 的數據被鎖住(注3),其它事務必須等待此次事務提交后才能執行SELECT * FROM products WHERE id=3 FOR UPDATE (注2)如此可以確保quantity 在別的事務讀到的數字是正確的。

 

UPDATE products SET quantity = '1' WHERE id=3 ;COMMIT WORK;

提交(Commit)寫入數據庫,products 解鎖。


注1: BEGIN/COMMIT 為事務的起始及結束點,可使用二個以上的MySQL Command 視窗來交互觀察鎖定的狀況。
注2: 在事務進行當中,只有SELECT ... FOR UPDATE 或LOCK IN SHARE MODE 同一筆數據時會等待其它事務結束后才執行,一般SELECT ... 則不受此影響。
注3: 由於InnoDB 預設為Row-level Lock,數據列的鎖定可參考這篇。
注4: InnoDB 表單盡量不要使用LOCK TABLES 指令,若情非得已要使用,請先看官方對於InnoDB 使用LOCK TABLES 的說明,以免造成系統經常發生死鎖。

 

MySQL SELECT ... FOR UPDATE 的Row Lock 與Table Lock
上面介紹過SELECT ... FOR UPDATE 的用法,不過鎖定(Lock)的數據是判別就得要注意一下了。由於InnoDB 預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL 才會執行Row lock (只鎖住被選取的數據) ,否則MySQL 將會執行Table Lock (將整個數據表單給鎖住)。
舉個例子:
假設有個表單products ,里面有id 跟name 二個欄位,id 是主鍵。
例1: (明確指定主鍵,並且有此數據,row lock)
SELECT * FROM products WHERE id='3' FOR UPDATE;
例2: (明確指定主鍵,若查無此數據,無lock)
SELECT * FROM products WHERE id='-1' FOR UPDATE;
例2: (無主鍵,table lock)
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
例3: (主鍵不明確,table lock)
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
例4: (主鍵不明確,table lock)
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
注1: FOR UPDATE 僅適用於InnoDB,且必須在事務區塊(BEGIN/COMMIT)中才能生效。
注2: 要測試鎖定的狀況,可以利用MySQL 的Command Mode ,開二個視窗來做測試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM