鍍金池/ 教程/ Java/ 數(shù)據(jù)庫訪問
數(shù)據(jù)庫訪問
循環(huán)
數(shù)組
錯誤處理
面向?qū)ο?/span>
調(diào)試
游戲開發(fā)
文件 I/O
變量
迭代器
Web 編程
模塊
函數(shù)
元表
協(xié)程
垃圾回收機制
標準庫
決策
數(shù)據(jù)類型
運行環(huán)境
操作符
字符串
基本語法
概述

數(shù)據(jù)庫訪問

簡單的數(shù)據(jù)操作,我們用文件就可以處理。但是,某些時候文件操作存在性能、擴展性等問題。這時候,我們就需要使用數(shù)據(jù)庫。LuaSQL 是一個提供數(shù)據(jù)庫操作的庫,它支持多種 SQL 數(shù)據(jù)庫的操作。包括:

  • SQLite
  • MySQL
  • ODBC

在本教程中,我們會講解用 Lua 語言對 MySQL 數(shù)據(jù)庫與 SQLite 數(shù)據(jù)庫進行操作。這些操作具有一般性,它們也可以移植到其它類型 SQL 數(shù)據(jù)庫中。首先讓我們看一下如何操作 MySQL 數(shù)據(jù)庫。

MySQL 數(shù)據(jù)庫環(huán)境設(shè)置

為了下面的例子可以正確演示,我們需要首先初始化數(shù)據(jù)庫設(shè)置。我們假設(shè)你已經(jīng)完成了如下的工作:

  • 安裝 MySQL 數(shù)據(jù)庫,使用默認用戶名 root, 默認密碼為: 123456。
  • 已經(jīng)創(chuàng)建數(shù)據(jù)庫 test。
  • 已經(jīng)閱讀過關(guān)于 MySQL 的基本教程,并掌握了 MySQL 的基本知識。

導(dǎo)入 MySQL

假設(shè)你已經(jīng)安裝配置正確了,那么我們可以使用 require 語句導(dǎo)入 sqlite 庫。安裝過程中會產(chǎn)生一個存儲數(shù)據(jù)相關(guān)文件的目錄 libsql。

mysql = require "luasql.mysql"

我們可以通過 mysql 變量訪問 luasql.mysql 中的 mysql 表,該表中存存儲數(shù)據(jù)庫操作相關(guān)的函數(shù)。

建立連接

先初始化 MySQL 的環(huán)境,再建立一個連接。如下所示:

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')

上面的程序會與已存在的 MySQL 數(shù)據(jù)庫 test 建立連接。

執(zhí)行函數(shù)

LuaSQL 庫中有一個 execute 函數(shù),此函數(shù)可以完成所有數(shù)據(jù)加操作,包括創(chuàng)建、插入、更新等操作。其語法如下所示:

conn:execute([[ 'MySQLSTATEMENT' ]])

執(zhí)行上面的語句這前,我們需要保證與 MySQL 數(shù)據(jù)庫的連接 conn 是打開的,同時將 MySQLSTATEMENT 更改為合法的 SQL 語句。

創(chuàng)建表

下面的示例演示如何創(chuàng)建一個數(shù)據(jù)庫表。例子中為表創(chuàng)建了兩個屬性分別為 id 和 name,其類型分別為整數(shù)和 vchar。

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample2 (id INTEGER, name TEXT);]])
print(status,errorString )

運行上面的程序后,數(shù)據(jù)庫中創(chuàng)建了一個表 sample,該表有兩列,屬性名分別為 id 和 name。

MySQL environment (004BB178)    MySQL connection (004BE3C8)
0   nil

如果發(fā)生錯誤,則函數(shù)將返回一個錯誤消息,成功執(zhí)行則返回 nil。下面是錯誤消息的一個例子:

LuaSQL: Error executing query. MySQL: 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 '"id INTEGER, name TEXT)' at line 1

插入語句

MySQL 插入語句的示例如下所示:

 conn:execute([[INSERT INTO sample values('11','Raj')]])

更新語句

MySQL 更新語句的示例如下所示:

conn:execute([[UPDATE sample3 SET name='John' where id ='12']])

刪除語句

MySQL 刪除語句的示例如下所示:

conn:execute([[DELETE from sample3 where id ='12']])

查找語句

成功查找返回后,我們需要循環(huán)遍歷返回的所有行以取得我們需要的數(shù)據(jù)。查找語句的示例如下:

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")
while row do
  print(string.format("Id: %s, Name: %s", row.id, row.name))
  -- reusing the table of results
  row = cursor:fetch (row, "a")
end

上面的代碼中,我們先打開了一個 MySQL 連接。通過 execute 函數(shù)返回的游標(cursor),我們可以使用游標遍歷返回的表,取得我們查找的數(shù)據(jù)。

完整示例

下面這個例子用到了所有上面提到的數(shù)據(jù)的操作函數(shù),請看下面這個完整的例子:

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample3 (id INTEGER, name TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample3 values('12','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample3]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")
while row do
  print(string.format("Id: %s, Name: %s", row.id, row.name))
  row = cursor:fetch (row, "a")
end
-- close everything
cursor:close()
conn:close()

運行上面的程序,我們可以得到如下的輸出結(jié)果:

MySQL environment (0037B178)    MySQL connection (0037EBA8)
0   nil
1   nil
MySQL cursor (003778A8) nil
Id: 12, Name: Raj

執(zhí)行事務(wù)

事務(wù)是數(shù)據(jù)庫中保證數(shù)據(jù)一致性的一種機制。事務(wù)有以下四個性質(zhì):

  • 原子性:一個事務(wù)要么全部執(zhí)行要么全部不執(zhí)行。
  • 一致性:事務(wù)開始前數(shù)據(jù)庫是一致狀態(tài),事務(wù)結(jié)束后數(shù)據(jù)庫狀態(tài)也應(yīng)該是一致的。
  • 隔離性:多個事務(wù)并發(fā)訪問時,事務(wù)之間是隔離的,一個事務(wù)的中間狀態(tài)不能被其它事務(wù)可見。
  • 持久性: 在事務(wù)完成以后,該事務(wù)所對數(shù)據(jù)庫所做的更改便持久的保存在數(shù)據(jù)庫之中,并不會被回滾。

事務(wù)以 START_TRANSACTION 開始,以 提交(commit)或 回滾(rollback)語句結(jié)束。

事務(wù)開始

為了初始化一個事務(wù),我們需要先打開一個 MySQL 連接,再執(zhí)行如下的語句:

conn:execute([[START TRANSACTION;]])

事務(wù)回滾

當(dāng)需要取消事務(wù)執(zhí)行時,我們需要執(zhí)行如下的語句回滾至更改前的狀態(tài)。

conn:execute([[ROLLBACK;]])

提交事務(wù)

開始執(zhí)行事務(wù)后,我們需要使用 commit 語句提交完成的修改內(nèi)容。

conn:execute([[COMMIT;]])

前面我們已經(jīng)了解了 MySQL 的基本知識。接下來,我們將解釋一下基本的 SQL 操作。請記住事務(wù)的概念,雖然我們在 SQLite3 中我們不在解釋它,但是它的概念在 SQLite3 中同樣適用。

導(dǎo)入 SQLite

假設(shè)你已經(jīng)安裝配置正確了,那么就可以使用 require 語句導(dǎo)入 sqlite 庫。安裝過程中會產(chǎn)生一個存儲數(shù)據(jù)相關(guān)文件的目錄 libsql。

 sqlite3 = require "luasql.sqlite3"

通過 sqlite3 變量可以訪問提供的所有數(shù)據(jù)庫操作相關(guān)函數(shù)。

建立連接

我們先初始化 sqlite 環(huán)境,然后為該環(huán)境創(chuàng)建一個連接。語法如下:

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')

上面的代碼會與一個 sqlite 文件建立連接,如果文件不存在則創(chuàng)建新的 sqlite 文件并與該新文件建立連接。

執(zhí)行函數(shù)

LuaSQL 庫中有一個 execute 函數(shù),此函數(shù)可以完成所有數(shù)據(jù)加操作,包括創(chuàng)建、插入、更新等操作。其語法如下所示:

conn:execute([[ 'SQLite3STATEMENT' ]])

執(zhí)行上面的語句這前,我們需要保證與 MySQL 數(shù)據(jù)庫的連接 conn 是打開的,同時將 SQLite3STATEMENT 更改為合法的 SQL 語句。

創(chuàng)建表

下面的示例演示如何創(chuàng)建一個數(shù)據(jù)庫表。例子中為表創(chuàng)建了兩個屬性分別為 id 和 name,其類型分別為整數(shù)和 vchar。

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

運行上面的程序后,數(shù)據(jù)庫中創(chuàng)建了一個表 sample,該表有兩列,屬性名分別為 id 和 name。

SQLite3 environment (003EC918)  SQLite3 connection (00421F08)
0   nil

如果發(fā)生錯誤,則函數(shù)將而一個錯誤消息;若成功執(zhí)行則返回 nil。下面是錯誤消息的一個例子:

LuaSQL: unrecognized token: ""'id' INTEGER, 'name' TEXT)"

插入語句

插入語句的示例如下所示:

 conn:execute([[INSERT INTO sample values('11','Raj')]])

查找語句

查找返回后,我們需要循環(huán)遍歷每行以取得我們需要的數(shù)據(jù)。查找語句的示例如下:

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")
while row do
  print(string.format("Id: %s, Name: %s", row.id, row.name))
  -- reusing the table of results
  row = cursor:fetch (row, "a")
end

上面的代碼中,我們先打開了一個 sqlite3 連接。通過 execute 函數(shù)返回的游標(cursor),我們可以遍歷返回的表,以取得我們查找的數(shù)據(jù)。

完整示例

下面這個例子用到了所有上面提到的數(shù)據(jù)的操作函數(shù),請看下面這個完整的例子:

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample values('1','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")
while row do
  print(string.format("Id: %s, Name: %s", row.id, row.name))
  row = cursor:fetch (row, "a")
end
-- close everything
cursor:close()
conn:close()
env:close()

運行上面的程序,我們可以得到如下的輸出結(jié)果:

SQLite3 environment (005EC918)  SQLite3 connection (005E77B0)
0   nil
1   nil
SQLite3 cursor (005E9200)   nil
Id: 1, Name: Raj

使用 libsql 庫我們可以執(zhí)行所有的數(shù)據(jù)庫操作。所以,看完這些例子后,請自己多做一些練習(xí)。