Lua 自身並沒有提供訪問數據庫的函數,但是借助外部擴展庫我們可以很容易實現對數據庫的各種操作,下面就為大家介紹這樣一個擴展庫 - LuaSQL,你可以在下載區得到它。
LuaSQL 定義了一套簡單的面向對象的 API,通過它,Lua 可以以統一的方法訪問各種流行的數據庫(例如 PostgreSQL,ODBC,JDBC,MySQL,SQLite,Oracle 和 ADO 等等)。
LuaSQL 在 Lua 中定義了一個名稱為 luasql 的全局表(用初始化函數 luaopen_luasqldrivername 生成),這個表儲存了載入數據庫驅動的初始化方法。這些方法可以創建一個環境對象,這些環境對象則可以創建數據庫的連接對象。連接對象可以執行各種 SQL 語句,最終產生游標對象。
環境對象
環境對象是由儲存在 luasql 表中的各種數據庫初始化函數創建的,這些函數的名稱和它們對應的數據庫名稱是一樣的。例如:
env = luasql.odbc()
這會使用 ODBC 驅動創建一個環境對象。JDBC 驅動比較特殊,你還必須讓它知道應該使用哪種內部驅動器,因此在創建環境對象時,你應該把驅動的類名作為參數傳遞給 luasql.jdbc 函數。例如:
env = luasql.jdbc("com.mysql.jdbc.Driver")
方法
env:close()
關閉環境對象。必須在與它相關的所有數據庫連接都關閉以后才應該調用這個函數。
返回值:關閉成功返回 true,關閉失敗或者環境對象已經被關閉了返回 false。
env:connect(sourcename[,username[,password]])
用指定的用戶名(username)和密碼(password)連接到數據源(sourcename)。
sourcename 根據數據庫驅動的不同而改變。有些只使用一個簡單的數據庫名稱即可,例如 MySQL, PostgreSQL 和 SQLite;ODBC 驅動需要一個 DSN 名稱;Oracle 驅動需要一個服務名稱;JDBC 驅動則需要一個字符串,就像“jdbc:<database system>://<database name>”一樣。
另見: PostgreSQL 擴展 和 MySQL 擴展。
返回值:一個連接對象。
連接對象
連接對象包含數據源連接的特殊屬性,它是由 environment:connect 創建的。
方法
conn:close()
關閉數據庫連接。只有在所有的游標都關閉的情況下才有可能成功關閉連接。
返回值:關閉成功返回 true,關閉失敗或者連接已經關閉了返回 false。
提交當前事務處理。此方法在不支持事務處理的數據庫上不會正常工作。 返回值:提交成功返回 true,提交失敗或者數據庫不支持事務處理則返回 false。
conn:execute(statement)
執行給定的 SQL 語句
返回值:一個游標對象,或者一個數字,指示有多少條記錄受此語句的影響。
回滾當前事務處理。此方法在不支持事務處理的數據庫上不會正常工作。 返回值:回滾成功返回 true,回滾失敗或者數據庫不支持事務處理則返回 false。
conn:setautocommit(boolean)
打開或者關閉“自動提交事務處理”功能。這個方法在不支持事務處理的數據庫上不會正常工作。在支持事務處理單不支持自動提交事務處理的數據庫上,會根據數據庫驅動的不同而有不同的結果。
返回值:設置成功返回 true,設置失敗或者數據庫不支持事務處理則返回 false。
游標對象
游標對象包含從 SQL 語句執行結果提取數據的各種方法。它是由 connection:execute 創建的。
方法
cur:close()
關閉游標對象。
返回值:關閉成功返回 true,關閉失敗或者游標對象已經關閉了返回 false。
獲取 SQL 語句執行結果中的下一條記錄結果。
如果調用此方法時沒有傳遞任何參數,結果會直接返回給方法的調用者。如果傳遞了 table 參數,結果會被復制到一個表(Lua 概念中的表)中並被返回。同時,你還可以指定一個 mode 參數,指示返回的表的所以方式。它有以下兩個值:
"n"
結果表以數字為索引標識符(默認)"a"
結果以字母為索引標識符
數字索引標識符的位置由執行的 SQL 語句中 select 后面的字段順序決定的;字母索引標識符則是根據字段的名稱來定的。
可選的 table 參數是用來儲存下一條記錄的。
此方法不保證返回結果的類型,這要由你所使用的數據庫驅動確定。目前來說,PostgreSQL 和 MySQL 驅動會把所有的結果都轉換為字符串,而 ODBC 和 Oracle 驅動則會根據字段類型返回對應的 Lua 類型的值
返回值:如上所述的數據結果,或者在沒有任何記錄結果時返回 nil。注意這並不是唯一返回 nil 的情況,當獲取的結果有效時也可能返回 nil。
返回值: 一個由字段名稱組成的表。
cur:getcoltypes()
返回值:一個由字段類型組成的表。
PostgreSQL 擴展
除了上面所說的通用的方法特性外,PostgreSQL 驅動還額外提供以下特性:
env:connect(sourcename[,username[,password[,hostname[,port]]]])
PostgreSQL 驅動的這個方法還提供了另外兩個可選的參數,指明了連接的主機名和端口號。當然,你也可以只用地一個參數就可以包含所有的連接信息,就像 PostgreSQL 手冊中 PQconnectdb 函數的參數一樣(例如,environment:connect("dbname=<name> user=<username>"))
另見:環境對象。
返回值:一個連接對象。
另見:游標對象
返回值:SQL 查詢結果的紀錄條數。
MySQL 擴展
除了上面所說的通用的方法特性外,MySQL 驅動還額外提供以下特性:
env:connect(sourcename[,username[,password[,hostname[,port]]]])
MySQL 驅動的這個方法還提供了另外兩個可選的參數,指明了連接的主機名和端口號。
另見:環境對象。
返回值:一個連接對象。
Oracle 擴展
除了上面所說的通用的方法特性外,Oracle 驅動還額外提供以下特性:
cur:numrows()
另見:游標對象
返回值:SQL 查詢結果的紀錄條數。
下面是用 Lua 訪問 Access 的一個簡單例子
-- 載入 ODBC 外部擴展庫
assert (loadlib ("odbc.dll", "luaopen_luasqlodbc")) ()
-- 創建環境對象
env = assert (luasql.odbc())
-- 連接數據庫
con = assert (env:connect ("luatest", -- DSN 名稱
"username", -- 用戶名
"password")) -- 密碼
-- 刪除數據庫中的 players 數據表
assert (con:execute"DROP TABLE players")
-- 創建 players 數據表
assert (con:execute[[
CREATE TABLE players(
name varchar(50),
class varchar(50)
)
]])
-- 添加一些記錄
list = {
{name="Nick Gammon", class="mage",},
{name="David Haley", class="warrior",},
{name="Shadowfyr", class="priest",}
}
for i, p in pairs (list) do
assert (con:execute(string.format([[
INSERT INTO players
VALUES ('%s', '%s')]], p.name, p.class)
))
end -- for loop
-- 執行一個查詢語句, 返回游標對象
cur = assert (con:execute ("SELECT * from players" ))
-- 打印結果中的所有記錄
row = cur:fetch ({}, "a")
while row do
print ("\n------ 新紀錄 ---------\n")
table.foreach (row, print)
-- 重復使用這個表, 以節省資源
row = cur:fetch (row, "a")
end -- while loop
-- 關閉和數據庫有關的所有對象
cur:close()
con:close()
env:close()
以下是用Lua操作mysql數據庫的過程
require "luasql.mysql"
--創建環境對象
env = luasql.mysql()
--連接數據庫
conn = env:connect("數據庫名","用戶名","密碼","IP地址",端口)
--設置數據庫的編碼格式
conn:execute"SET NAMES GB2312"
--執行數據庫操作
cur = conn:execute("select * from role")
row = cur:fetch({},"a")
--文件對象的創建
file = io.open("role.dat","w+");
while row do
var = string.format("%d %s\n", row.id, row.name)
print(var)
file:write(var)
row = cur:fetch(row,"a")
end
file:close() --關閉文件對象
conn:close() --關閉數據庫連接
env:close() --關閉數據庫環境