數(shù)據(jù)表定義語句(DDL)
創(chuàng)建表:
create table if not exists <biaoming> (id integer primary key autoincrement,name text not NULL, age integer default 60)
刪除表:
drop table if exists <biaoming>
更改表名:
alter table <biaoming> rename to <xinbiaoming>
給表增加列:
alter table <biaoming> add column <lieming> name text <zhibiaofu>
數(shù)據(jù)表操作語句(DML)
增加:
insert into <biaoming> (name, age,score) values {'xiaowang',90,80}
修改:
update <> set name = 'xiaohong',age = 20
update <> set score = 30 where id > 30
刪除:
delete from <> where age is 18
DQL:查詢語句
select name, age from <>
select * from <>
統(tǒng)計(jì):
記錄所有age不為空的個(gè)數(shù)(記錄)select count(age) from <>
記錄某個(gè)字段平均值 select avg(age) from <>
求和:sum zuida:max zuixiao:min
排序:
select *from <> order by score ASC(升序) 或者用 DESC(降序)
select *from <> order by score ASC死陆,age DESC
分頁(yè):
select * from <> limit 1,3 1表示跳過1條,3表示跳過3條
多表查詢:
OC中代碼:
創(chuàng)建數(shù)據(jù)庫(kù)
//參數(shù)1.數(shù)據(jù)庫(kù)文件的路徑 2.數(shù)據(jù)庫(kù)對(duì)象,要打開的數(shù)據(jù)庫(kù)
//返回值表示操作的狀態(tài)碼
int result = sqlite3_open(filename, &_db);
if (result == SQLITE_OK)
{
NSLog(@"數(shù)據(jù)庫(kù)打開成功");
return YES;
}
else
{
NSLog(@"數(shù)據(jù)庫(kù)打開失敗");
//sqlite3_close 關(guān)閉數(shù)據(jù)庫(kù)的方法
sqlite3_close(_db);
return NO;
}
創(chuàng)建表
char *error = nil;
//sqlite3_exec對(duì)數(shù)據(jù)庫(kù)的操作:創(chuàng)建表,增刪改,都建議用這個(gè)方法,查建議用其他的
//參數(shù) 1.數(shù)據(jù)庫(kù)對(duì)象 2.sql語句 3.回調(diào)函數(shù)nil 4.回調(diào)函數(shù)的參數(shù)nil
if (sqlite3_exec(_db, [str UTF8String], nil, nil, &error)==SQLITE_OK)
{
NSLog(@"創(chuàng)建表成功");
}
else
{
NSLog(@"創(chuàng)建表失敗:%s",error);
}
增刪改查
//第一種方式sqlite3_exec
//sql為相關(guān)的增刪改語句
sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK
//另一種方式,預(yù)處理語句sqlite3_prepare_v2
let prepareSql = "INSERT INTO \(tableName)(\(columnNames)) values (\(valuesStr))"
var stmt: COpaquePointer = nil
// 預(yù)處理SQL語句, 并生成 "語句句柄" , 后續(xù)會(huì)使用這樣的語句句柄綁定數(shù)值, 并執(zhí)行
if sqlite3_prepare_v2(db, prepareSql, -1, &stmt, nil) != SQLITE_OK
{
print("預(yù)處理失敗")
// 釋放語句資源
sqlite3_finalize(stmt)
return false
}
var index: Int32 = 1
for obj in values
{
if obj is Int
{
let temp: sqlite_int64 = obj as! sqlite_int64
sqlite3_bind_int64(stmt, index, temp)
} else if obj is Double
{
sqlite3_bind_double(stmt, index, obj as! Double)
}else if obj is String
{
/**
第5個(gè)參數(shù)
此參數(shù)有兩個(gè)常數(shù)凉袱,SQLITE_STATIC告訴sqlite3_bind_text函數(shù)字符串為常量版述,可以放心使用;
而SQLITE_TRANSIENT會(huì)使得sqlite3_bind_text函數(shù)對(duì)字符串做一份拷貝婿失。
一般使用這兩個(gè)常量參數(shù)來調(diào)用sqlite3_bind_text嫩痰。
*/
sqlite3_bind_text(stmt, index, obj as! String, -1, SQLITE_TRANSIENT)
}else {
continue
}
index++
}
var result: Bool = false
if sqlite3_step(stmt) == SQLITE_DONE
{
print("插入成功")
result = true
}else
{
print("插入失敗")
result = false
}
// 將語句復(fù)位
if sqlite3_reset(stmt) != SQLITE_OK
{
print("復(fù)位失敗")
result = false
}
// 釋放語句
sqlite3_finalize(stmt)
return result
處理大數(shù)據(jù)耗時(shí)問題
插入10000條數(shù)據(jù)
sqlite_exec 10000 5.8080689907074
sqlite_prepare 10000 5.93309998512268
sqlite_prepare 分解后, 準(zhǔn)備1次, 多次綁定/重置, 一次釋放 5.11254101991653
分析結(jié)果
所以: 如果執(zhí)行單條語句的話, 兩者效率幾乎一致
如果執(zhí)行多條語句, 建議使用"準(zhǔn)備語句"
兩者區(qū)別:
sqlite_exec 函數(shù)是對(duì)"準(zhǔn)備語句"的封裝 (預(yù)處理語句->綁定參數(shù)->執(zhí)行語句->重置語句->釋放語句)
如果需要綁定二進(jìn)制數(shù)據(jù), 就必須要使用"準(zhǔn)備語句了"
sqlite_exec 用法相對(duì)簡(jiǎn)單
整體耗時(shí), 依然達(dá)到5秒左右, 非常龐大
原因: 因?yàn)閟qlite3_exec, 或者 sqlite3_step 執(zhí)行語句時(shí), 都會(huì)自動(dòng)開啟事務(wù)-> 執(zhí)行語句 -> 提交事務(wù) 這樣的流程, 所以造成了, 多次開啟和提交事務(wù), 這個(gè)是非常耗時(shí)的操作
解決方案: 手動(dòng)開啟和提交事務(wù)即可, 這樣 系統(tǒng)就不會(huì)自動(dòng)開啟事務(wù)和提交事務(wù)了
代碼:
XMGSQLTool.shareInstance.beginTransaction()
for _ in 0...9999 {
stu.insertStudent()
}
XMGSQLTool.shareInstance.commitTransaction()
/** 開啟事務(wù) */
func beginTransaction() -> Bool
{
let sql = "BEGIN TRANSACTION"
return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
}
/** 提交事務(wù) */
func commitTransaction() -> Bool
{
let sql = "COMMIT TRANSACTION"
return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
}
/** 回滾事務(wù)*/
func rollBackTransaction() -> Bool
{
let sql = "ROLLBACK TRANSACTION"
return (sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK)
}
開啟事務(wù)BEGIN TRANSACTION
提交事務(wù)COMMIT TRANSACTION
回滾事務(wù)ROLLBACK TRANSACTION
查詢的兩種方式
let selectSql = "select * from t_student"
// 方式1:
// 參數(shù)1: 一個(gè)打開的數(shù)據(jù)庫(kù)
// 參數(shù)2: 需要執(zhí)行的SQL語句
// 參數(shù)3: 查詢結(jié)果回調(diào)(執(zhí)行0次或多次)
// 參數(shù)1: 參數(shù)4的值
// 參數(shù)2: 列的個(gè)數(shù)
// 參數(shù)3: 結(jié)果值的數(shù)組
// 參數(shù)4: 所有列的名稱數(shù)組
// 返回值: 0代表繼續(xù)執(zhí)行一致到結(jié)束, 1代表執(zhí)行一次
// 參數(shù)4: 回調(diào)函數(shù)的第一個(gè)值
// 參數(shù)5: 錯(cuò)誤信息
sqlite3_exec(db, selectSql, { (parameter: UnsafeMutablePointer<Void>, columnCount: Int32, values: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>, columnNames: UnsafeMutablePointer<UnsafeMutablePointer<Int8>>) -> Int32 in
let count = Int(columnCount)
for i: Int in 0..<count
{
let column = columnNames[i]
let columnStr = String(CString: column, encoding: NSUTF8StringEncoding)
let value = values[i]
let valueStr = String(CString: value, encoding: NSUTF8StringEncoding)
print(columnStr! + "= " + valueStr!)
}
return 0
}, nil, nil)
// 方式2:
// var stmt: COpaquePointer = nil
// if sqlite3_prepare(db, selectSql, -1, &stmt, nil) != SQLITE_OK
// {
// print("預(yù)處理失敗")
// return
// }
//
// // 因?yàn)椴樵冋Z句中沒有占位?, 所以, 可以省略"綁定步驟"
// // 執(zhí)行語句
// // sqlite3_step, 當(dāng)使用這個(gè)方法時(shí), 執(zhí)行完畢后, 會(huì)自動(dòng)跳到結(jié)果集的下一行, 如果依然有記錄就返回SQLITE_ROW,
// while sqlite3_step(stmt) == SQLITE_ROW
// {
// let columnCount = sqlite3_column_count(stmt)
//
// for i in 0..<columnCount
// {
//
// // 獲取列的類型
// let type = sqlite3_column_type(stmt, i)
//
// if type == SQLITE_TEXT
// {
// let text = UnsafePointer<Int8>(sqlite3_column_text(stmt, i))
// let str = String(CString: text, encoding: NSUTF8StringEncoding)
// print(str)
// }
//
// }
//
// }
//
// sqlite3_finalize(stmt)
FMDB使用:
優(yōu)勢(shì):1.封裝 2.提供了多線程訪問數(shù)據(jù)方式
三個(gè)主要的類:
FMDatabase:是一個(gè)提供 SQLite 數(shù)據(jù)庫(kù)的類剿吻,用于執(zhí)行 SQL 語句。
FMResultSet:用在 FMDatabase 中執(zhí)行查詢的結(jié)果的類串纺。
FMDatabaseQueue:在多線程下查詢和更新數(shù)據(jù)庫(kù)用到的類丽旅。
數(shù)據(jù)庫(kù)創(chuàng)建
FMDatabase 是通過一個(gè) SQLite 數(shù)據(jù)庫(kù)文件路徑創(chuàng)建的,此路徑可以是以下三者之一:
一個(gè)文件的系統(tǒng)路徑纺棺。磁盤中可以不存在此文件魔招,因?yàn)槿绻淮嬖跁?huì)自動(dòng)為你創(chuàng)建。
一個(gè)空的字符串 @""五辽。會(huì)在臨時(shí)位置創(chuàng)建一個(gè)空的數(shù)據(jù)庫(kù),當(dāng) FMDatabase 連接關(guān)閉時(shí)外恕,該數(shù)據(jù)庫(kù)會(huì)被刪除杆逗。
NULL。會(huì)在內(nèi)存中創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)鳞疲,當(dāng) FMDatabase 連接關(guān)閉時(shí)罪郊,該數(shù)據(jù)庫(kù)會(huì)被銷毀。
推薦文章:
[an example]http://www.reibang.com/p/d60ee3c85d63