我正在寻找一种使用Swift代码在我的应用中访问SQLite数据库的方法。
我知道我可以在Objective C中使用SQLite Wrapper并使用桥接头,但我完全可以在Swift中完成这个项目。有没有办法做到这一点,如果是这样,有人可以指向我一个显示如何提交查询,检索行等的参考?
答案 0 :(得分:128)
虽然你应该使用众多SQLite包装器中的一个(我更喜欢自己FMDB),如果你想知道如何自己调用SQLite库,你会:
配置Swift项目以处理SQLite C调用。如果使用Xcode 9,您只需执行以下操作:
import SQLite3
在早期版本的Xcode中,您可以:
为项目创建桥接头文件。请参阅Using Swift with Cocoa and Objective-C中的将Objective-C导入Swift 部分。此桥接标头应导入sqlite3.h
:
#import <sqlite3.h>
将libsqlite3.tbd
(或更旧的版本,libsqlite3.dylib
)添加到您的项目中:
创建/打开数据库。
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("test.sqlite")
// open database
var db: OpaquePointer?
if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
print("error opening database")
}
使用sqlite3_exec
执行SQL(例如创建表格)。
if sqlite3_exec(db, "create table if not exists test (id integer primary key autoincrement, name text)", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}
使用sqlite3_prepare_v2
为?
占位符准备SQL,我们将绑定值。
var statement: OpaquePointer?
if sqlite3_prepare_v2(db, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "foo", -1, SQLITE_TRANSIENT) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding foo: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting foo: \(errmsg)")
}
注意,它使用SQLITE_TRANSIENT
常量which can be implemented,如下所示:
internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)
重置SQL以插入另一个值。在此示例中,我将插入NULL
值:
if sqlite3_reset(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error resetting prepared statement: \(errmsg)")
}
if sqlite3_bind_null(statement, 1) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding null: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting null: \(errmsg)")
}
完成预准备语句以恢复与该预准备语句关联的内存:
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nil
准备新的语句,用于从表中选择值并循环检索值:
if sqlite3_prepare_v2(db, "select id, name from test", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing select: \(errmsg)")
}
while sqlite3_step(statement) == SQLITE_ROW {
let id = sqlite3_column_int64(statement, 0)
print("id = \(id); ", terminator: "")
if let cString = sqlite3_column_text(statement, 1) {
let name = String(cString: cString)
print("name = \(name)")
} else {
print("name not found")
}
}
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nil
关闭数据库:
if sqlite3_close(db) != SQLITE_OK {
print("error closing database")
}
db = nil
对于Swift 2,请参阅previous revision of this answer。
答案 1 :(得分:17)
您可以做的最好的事情是在桥接标头中导入动态库:
#import <sqlite3.h>
添加到顶部然后,您就可以从swift代码中访问所有c方法,例如sqlite3_open
。
但是,您可能只想使用FMDB并通过桥接头导入它,因为这是一个更面向对象的sqlite包装器。在Swift中处理C指针和结构将很麻烦。
答案 2 :(得分:11)
我也在寻找与SQLite交互的方式,就像我之前在Objective-C中所做的那样。不可否认,由于C兼容性,我只使用了直接的C API。
由于Swift中SQLite当前不存在包装器,并且上面提到的SQLiteDB代码更高级并假设使用了一些,我决定创建一个包装器并在此过程中熟悉Swift。您可以在此处找到它:https://github.com/chrismsimpson/SwiftSQLite。
var db = SQLiteDatabase();
db.open("/path/to/database.sqlite");
var statement = SQLiteStatement(database: db);
if ( statement.prepare("SELECT * FROM tableName WHERE Id = ?") != .Ok )
{
/* handle error */
}
statement.bindInt(1, value: 123);
if ( statement.step() == .Row )
{
/* do something with statement */
var id:Int = statement.getIntAt(0)
var stringValue:String? = statement.getStringAt(1)
var boolValue:Bool = statement.getBoolAt(2)
var dateValue:NSDate? = statement.getDateAt(3)
}
statement.finalizeStatement(); /* not called finalize() due to destructor/language keyword */
答案 3 :(得分:4)
我创建了一个优雅的SQLite库,完全用Swift编写,名为SwiftData。
它的一些功能是:
它提供了一种执行“更改”的简便方法(例如INSERT,UPDATE,DELETE等):
if let err = SD.executeChange("INSERT INTO Cities (Name, Population, IsWarm, FoundedIn) VALUES ('Toronto', 2615060, 0, '1793-08-27')") {
//there was an error during the insert, handle it here
} else {
//no error, the row was inserted successfully
}
和'queries'(例如SELECT):
let (resultSet, err) = SD.executeQuery("SELECT * FROM Cities")
if err != nil {
//there was an error during the query, handle it here
} else {
for row in resultSet {
if let name = row["Name"].asString() {
println("The City name is: \(name)")
}
if let population = row["Population"].asInt() {
println("The population is: \(population)")
}
if let isWarm = row["IsWarm"].asBool() {
if isWarm {
println("The city is warm")
} else {
println("The city is cold")
}
}
if let foundedIn = row["FoundedIn"].asDate() {
println("The city was founded in: \(foundedIn)")
}
}
}
还有更多功能!
您可以查看here
答案 4 :(得分:2)
Swift 2和Swift 3的另一个SQLite包装器:http://github.com/groue/GRDB.swift
特点:
利用Swift标准库的低级SQLite API
适用于SQL过敏开发者的漂亮Swift查询界面
支持SQLite WAL模式和并发数据库访问以获得额外性能
一个记录类,它包装结果集,吃早餐的自定义SQL查询,并提供基本的CRUD操作
Swift类型自由:选择适合您数据的Swift类型。需要时使用Int64,或坚持使用方便的Int。存储和读取NSDate或NSDateComponents。为离散数据类型声明Swift枚举。定义您自己的数据库可转换类型。
数据库迁移
答案 5 :(得分:2)
AppDelegate.swift
func createDatabase()
{
var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let directory:String=path[0]
let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")
print(DBpath)
if (FileManager.default.fileExists(atPath: DBpath))
{
print("Successfull database create")
}
else
{
let pathfrom:String=(Bundle.main.resourcePath! as NSString).appendingPathComponent("Food.sqlite")
var success:Bool
do {
try FileManager.default.copyItem(atPath: pathfrom, toPath: DBpath)
success = true
} catch _ {
success = false
}
if !success
{
print("database not create ")
}
else
{
print("Successfull database new create")
}
}
}
Database.swift
import UIKit
class database: NSObject
{
func databasePath() -> NSString
{
var path:Array=NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let directory:String=path[0]
let DBpath=(directory as NSString).appendingPathComponent("Food.sqlite")
if (FileManager.default.fileExists(atPath: DBpath))
{
return DBpath as NSString
}
return DBpath as NSString
}
func ExecuteQuery(_ str:String) -> Bool
{
var result:Bool=false
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if (sqlite3_open(DBpath, &db)==SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
if (sqlite3_step(stmt) == SQLITE_DONE)
{
result=true
}
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
return result
}
func SelectQuery(_ str:String) -> Array<Dictionary<String,String>>
{
var result:Array<Dictionary<String,String>>=[]
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
while (sqlite3_step(stmt) == SQLITE_ROW)
{
var i:Int32=0
let icount:Int32=sqlite3_column_count(stmt)
var dict=Dictionary<String, String>()
while i < icount
{
let strF=sqlite3_column_name(stmt, i)
let strV = sqlite3_column_text(stmt, i)
let rFiled:String=String(cString: strF!)
let rValue:String=String(cString: strV!)
//let rValue=String(cString: UnsafePointer<Int8>(strV!))
dict[rFiled] = rValue
i += 1
}
result.insert(dict, at: result.count)
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
}
return result
}
func AllSelectQuery(_ str:String) -> Array<Model>
{
var result:Array<Model>=[]
let DBpath:String=self.databasePath() as String
var db: OpaquePointer? = nil
var stmt:OpaquePointer? = nil
let strExec=str.cString(using: String.Encoding.utf8)
if ( sqlite3_open(DBpath,&db) == SQLITE_OK)
{
if (sqlite3_prepare_v2(db, strExec! , -1, &stmt, nil) == SQLITE_OK)
{
while (sqlite3_step(stmt) == SQLITE_ROW)
{
let mod=Model()
mod.id=String(cString: sqlite3_column_text(stmt, 0))
mod.image=String(cString: sqlite3_column_text(stmt, 1))
mod.name=String(cString: sqlite3_column_text(stmt, 2))
mod.foodtype=String(cString: sqlite3_column_text(stmt, 3))
mod.vegtype=String(cString: sqlite3_column_text(stmt, 4))
mod.details=String(cString: sqlite3_column_text(stmt, 5))
result.insert(mod, at: result.count)
}
sqlite3_finalize(stmt)
}
sqlite3_close(db)
}
return result
}
}
Model.swift
import UIKit
class Model: NSObject
{
var uid:Int = 0
var id:String = ""
var image:String = ""
var name:String = ""
var foodtype:String = ""
var vegtype:String = ""
var details:String = ""
var mealtype:String = ""
var date:String = ""
}
访问数据库:
let DB=database()
var mod=Model()
数据库查询:
var DailyResult:Array<Model> = DB.AllSelectQuery("select * from food where foodtype == 'Sea Food' ORDER BY name ASC")
答案 6 :(得分:0)
我写过a SQLite3 wrapper library written in Swift。
这实际上是一个非常高级的包装器,具有非常简单的API,但无论如何,它具有低级别的C语言间操作代码,我在这里发布了一个(简化的)部分来显示C inter-op。 / p>
struct C
{
static let NULL = COpaquePointer.null()
}
func open(filename:String, flags:OpenFlag)
{
let name2 = filename.cStringUsingEncoding(NSUTF8StringEncoding)!
let r = sqlite3_open_v2(name2, &_rawptr, flags.value, UnsafePointer<Int8>.null())
checkNoErrorWith(resultCode: r)
}
func close()
{
let r = sqlite3_close(_rawptr)
checkNoErrorWith(resultCode: r)
_rawptr = C.NULL
}
func prepare(SQL:String) -> (statements:[Core.Statement], tail:String)
{
func once(zSql:UnsafePointer<Int8>, len:Int32, inout zTail:UnsafePointer<Int8>) -> Core.Statement?
{
var pStmt = C.NULL
let r = sqlite3_prepare_v2(_rawptr, zSql, len, &pStmt, &zTail)
checkNoErrorWith(resultCode: r)
if pStmt == C.NULL
{
return nil
}
return Core.Statement(database: self, pointerToRawCStatementObject: pStmt)
}
var stmts:[Core.Statement] = []
let sql2 = SQL as NSString
var zSql = UnsafePointer<Int8>(sql2.UTF8String)
var zTail = UnsafePointer<Int8>.null()
var len1 = sql2.lengthOfBytesUsingEncoding(NSUTF8StringEncoding);
var maxlen2 = Int32(len1)+1
while let one = once(zSql, maxlen2, &zTail)
{
stmts.append(one)
zSql = zTail
}
let rest1 = String.fromCString(zTail)
let rest2 = rest1 == nil ? "" : rest1!
return (stmts, rest2)
}
func step() -> Bool
{
let rc1 = sqlite3_step(_rawptr)
switch rc1
{
case SQLITE_ROW:
return true
case SQLITE_DONE:
return false
default:
database.checkNoErrorWith(resultCode: rc1)
}
}
func columnText(at index:Int32) -> String
{
let bc = sqlite3_column_bytes(_rawptr, Int32(index))
let cs = sqlite3_column_text(_rawptr, Int32(index))
let s1 = bc == 0 ? "" : String.fromCString(UnsafePointer<CChar>(cs))!
return s1
}
func finalize()
{
let r = sqlite3_finalize(_rawptr)
database.checkNoErrorWith(resultCode: r)
_rawptr = C.NULL
}
如果您需要此低级包装器的完整源代码,请参阅这些文件。
答案 7 :(得分:0)
配置Swift项目以处理SQLite C调用:
为项目创建桥接头文件。请参阅使用Swift with Cocoa和Objective-C将Importing-C导入到Swift部分。这个桥接头应该导入sqlite3.h:
将libsqlite3.0.dylib添加到项目中。请参阅Apple关于将库/框架添加到某个项目的文档。
并使用以下代码
func executeQuery(query: NSString ) -> Int
{
if sqlite3_open(databasePath! as String, &database) != SQLITE_OK
{
println("Databse is not open")
return 0
}
else
{
query.stringByReplacingOccurrencesOfString("null", withString: "")
var cStatement:COpaquePointer = nil
var executeSql = query as NSString
var lastId : Int?
var sqlStatement = executeSql.cStringUsingEncoding(NSUTF8StringEncoding)
sqlite3_prepare_v2(database, sqlStatement, -1, &cStatement, nil)
var execute = sqlite3_step(cStatement)
println("\(execute)")
if execute == SQLITE_DONE
{
lastId = Int(sqlite3_last_insert_rowid(database))
}
else
{
println("Error in Run Statement :- \(sqlite3_errmsg16(database))")
}
sqlite3_finalize(cStatement)
return lastId!
}
}
func ViewAllData(query: NSString, error: NSError) -> NSArray
{
var cStatement = COpaquePointer()
var result : AnyObject = NSNull()
var thisArray : NSMutableArray = NSMutableArray(capacity: 4)
cStatement = prepare(query)
if cStatement != nil
{
while sqlite3_step(cStatement) == SQLITE_ROW
{
result = NSNull()
var thisDict : NSMutableDictionary = NSMutableDictionary(capacity: 4)
for var i = 0 ; i < Int(sqlite3_column_count(cStatement)) ; i++
{
if sqlite3_column_type(cStatement, Int32(i)) == 0
{
continue
}
if sqlite3_column_decltype(cStatement, Int32(i)) != nil && strcasecmp(sqlite3_column_decltype(cStatement, Int32(i)), "Boolean") == 0
{
var temp = sqlite3_column_int(cStatement, Int32(i))
if temp == 0
{
result = NSNumber(bool : false)
}
else
{
result = NSNumber(bool : true)
}
}
else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_INTEGER
{
var temp = sqlite3_column_int(cStatement,Int32(i))
result = NSNumber(int : temp)
}
else if sqlite3_column_type(cStatement,Int32(i)) == SQLITE_FLOAT
{
var temp = sqlite3_column_double(cStatement,Int32(i))
result = NSNumber(double: temp)
}
else
{
if sqlite3_column_text(cStatement, Int32(i)) != nil
{
var temp = sqlite3_column_text(cStatement,Int32(i))
result = String.fromCString(UnsafePointer<CChar>(temp))!
var keyString = sqlite3_column_name(cStatement,Int32(i))
thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
}
result = NSNull()
}
if result as! NSObject != NSNull()
{
var keyString = sqlite3_column_name(cStatement,Int32(i))
thisDict.setObject(result, forKey: String.fromCString(UnsafePointer<CChar>(keyString))!)
}
}
thisArray.addObject(NSMutableDictionary(dictionary: thisDict))
}
sqlite3_finalize(cStatement)
}
return thisArray
}
func prepare(sql : NSString) -> COpaquePointer
{
var cStatement:COpaquePointer = nil
sqlite3_open(databasePath! as String, &database)
var utfSql = sql.UTF8String
if sqlite3_prepare(database, utfSql, -1, &cStatement, nil) == 0
{
sqlite3_close(database)
return cStatement
}
else
{
sqlite3_close(database)
return nil
}
}
}
答案 8 :(得分:0)
有时,"SQLite in 5 minutes or less"上显示的sqlite.org方法的Swift版本就足够了。
&#34; 5分钟或更短时间&#34;方法使用sqlite3_exec()
,它是sqlite3_prepare()
,sqlite3_step()
,sqlite3_column()
和sqlite3_finalize()
的便捷包装。
Swift 2.2可以直接支持sqlite3_exec()
callback
函数指针作为全局非实例过程func
或非捕获文字闭包{}
的
可读typealias
typealias sqlite3 = COpaquePointer
typealias CCharHandle = UnsafeMutablePointer<UnsafeMutablePointer<CChar>>
typealias CCharPointer = UnsafeMutablePointer<CChar>
typealias CVoidPointer = UnsafeMutablePointer<Void>
回调方法
func callback(
resultVoidPointer: CVoidPointer, // void *NotUsed
columnCount: CInt, // int argc
values: CCharHandle, // char **argv
columns: CCharHandle // char **azColName
) -> CInt {
for i in 0 ..< Int(columnCount) {
guard let value = String.fromCString(values[i])
else { continue }
guard let column = String.fromCString(columns[i])
else { continue }
print("\(column) = \(value)")
}
return 0 // status ok
}
func sqlQueryCallbackBasic(argc: Int, argv: [String]) -> Int {
var db: sqlite3 = nil
var zErrMsg:CCharPointer = nil
var rc: Int32 = 0 // result code
if argc != 3 {
print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
return 1
}
rc = sqlite3_open(argv[1], &db)
if rc != 0 {
print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
sqlite3_close(db)
return 1
}
rc = sqlite3_exec(db, argv[2], callback, nil, &zErrMsg)
if rc != SQLITE_OK {
print("ERROR: sqlite3_exec " + String.fromCString(zErrMsg)! ?? "")
sqlite3_free(zErrMsg)
}
sqlite3_close(db)
return 0
}
关闭方法
func sqlQueryClosureBasic(argc argc: Int, argv: [String]) -> Int {
var db: sqlite3 = nil
var zErrMsg:CCharPointer = nil
var rc: Int32 = 0
if argc != 3 {
print(String(format: "ERROR: Usage: %s DATABASE SQL-STATEMENT", argv[0]))
return 1
}
rc = sqlite3_open(argv[1], &db)
if rc != 0 {
print("ERROR: sqlite3_open " + String.fromCString(sqlite3_errmsg(db))! ?? "" )
sqlite3_close(db)
return 1
}
rc = sqlite3_exec(
db, // database
argv[2], // statement
{ // callback: non-capturing closure
resultVoidPointer, columnCount, values, columns in
for i in 0 ..< Int(columnCount) {
guard let value = String.fromCString(values[i])
else { continue }
guard let column = String.fromCString(columns[i])
else { continue }
print("\(column) = \(value)")
}
return 0
},
nil,
&zErrMsg
)
if rc != SQLITE_OK {
let errorMsg = String.fromCString(zErrMsg)! ?? ""
print("ERROR: sqlite3_exec \(errorMsg)")
sqlite3_free(zErrMsg)
}
sqlite3_close(db)
return 0
}
要准备一个Xcode项目来调用诸如SQLite之类的C库,需要(1)添加一个Bridging-Header.h文件引用C头像#import "sqlite3.h"
,(2)添加Bridging-Header.h在项目设置中 Objective-C Bridging Header ,以及(3)将libsqlite3.tbd
添加到 Link Binary With Library 目标设置。
sqlite.org的"SQLite in 5 minutes or less"示例是在Swift Xcode7项目here中实现的。
答案 9 :(得分:0)
你也可以使用单一类来轻松配置SQLite。
<强>参见强>
https://github.com/hasyapanchasara/SQLite_SingleManagerClass
创建数据库的方法
func methodToCreateDatabase() -> NSURL?{}
插入,更新和删除数据的方法
func methodToInsertUpdateDeleteData(strQuery : String) -> Bool{}
选择数据的方法
func methodToSelectData(strQuery : String) -> NSMutableArray{}
答案 10 :(得分:0)
您可以在Swift for SQLite中使用此库 https://github.com/pmurphyjam/SQLiteDemo
使用Swift编写的SQLite Demo与使用Swift编写的SQLDataAccess类
您只需要将三个文件添加到项目中 * SQLDataAccess.swift * DataConstants.swift * Bridging-Header.h 必须在Xcode的项目'Swift Compiler - General'下的'Objective-C Bridging Header'中设置Bridging-Header
只需按照ViewController.swift中的代码查看如何使用SQLDataAccess.swift编写简单的SQL 首先,您需要打开处理
的SQLite数据库```swift
let db = SQLDataAccess.shared
db.setDBName(name:"SQLite.db")
let opened = db.openConnection(copyFile:true)
```
如果openConnection成功,现在您可以在表AppInfo
中进行简单的插入```swift
//Insert into Table AppInfo
let status = db.executeStatement("insert into AppInfo (name,value,descrip,date) values(?,?,?,?)",
”SQLiteDemo","1.0.2","unencrypted",Date())
if(status)
{
//Read Table AppInfo into an Array of Dictionaries
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
```
看看有多简单!
db.executeStatement中的第一个术语是SQL as String,后面的所有术语都是Any类型的可变参数列表,并且是数组中的参数。所有这些术语在SQL参数列表中用逗号分隔。您可以在续集声明之后输入字符串,整数,日期和Blob,因为所有这些术语都被认为是续集的参数。可变参数数组只是方便您在一个executeStatement或getRecordsForQuery调用中输入所有续集。如果您没有任何参数,请不要在SQL之后输入任何内容。
结果数组是一个Dictionary字典数组,其中'key'是表的列名,'value'是从SQLite获得的数据。您可以使用for循环轻松遍历此数组或直接将其打印出来,或将这些Dictionary元素分配给您在View Controllers中用于模型消费的自定义数据对象类。
```swift
for dic in results as! [[String:AnyObject]] {
print(“result = \(dic)”)
}
```
SQLDataAccess将存储,文本,双精度,浮点数,blob,日期,整数和长整数。 对于Blob,您可以存储binary,varbinary,blob。
对于Text,您可以存储char,character,clob,国家变化字符,本机字符,nchar,nvarchar,varchar,变体,变化字符,文本。
对于日期,您可以存储日期时间,时间,时间戳,日期。
对于整数,你可以存储bigint,bit,bool,boolean,int2,int8,integer,mediumint,smallint,tinyint,int。
对于双打,你可以存储十进制,双精度,浮点数,数字,真实,双精度。双精度最高。
您甚至可以存储Null类型的Null。
在ViewController.swift中,一个更复杂的例子展示了如何将Dictionary作为'Blob'插入。另外还有SQLDataAccess 了解原生Swift Date(),因此您可以插入这些对象而不进行转换,并将它们转换为文本并存储它们, 检索时将它们从文本转换回日期。
当然,SQLite的真正威力在于它的交易能力。在这里,您可以使用参数排队400个SQL语句 并将它们全部插入,这非常强大,因为它非常快。 ViewController.swift还向您展示了如何执行此操作的示例。 所有你真正要做的就是创建一个名为'sqlAndParams'的字典数组,在这个数组中你存储有两个键的字典 字符串续集语句或查询的'SQL'和'PARAMS',它只是SQLite对该查询理解的本机对象数组。 每个'sqlParams'是一个单独的续集查询字典和参数,然后存储在'sqlAndParams'数组中。 创建此数组后,只需调用。
```swift
let status = db.executeTransaction(sqlAndParams)
if(status)
{
//Read Table AppInfo into an Array of Dictionaries for the above Transactions
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
```
此外,所有executeStatement和getRecordsForQuery方法都可以使用简单的String for SQL查询和一个数组来完成查询所需的参数。
```swift
let sql : String = "insert into AppInfo (name,value,descrip) values(?,?,?)"
let params : Array = ["SQLiteDemo","1.0.0","unencrypted"]
let status = db.executeStatement(sql, withParameters: params)
if(status)
{
//Read Table AppInfo into an Array of Dictionaries for the above Transactions
let results = db.getRecordsForQuery("select * from AppInfo ")
NSLog("Results = \(results)")
}
```
Objective-C版本也存在并被称为相同的SQLDataAccess,所以现在您可以选择在Objective-C或Swift中编写续集。 此外,SQLDataAccess也可以与SQLCipher一起使用,目前的代码还没有设置好使用它,但它很容易做到,并且 一个如何执行此操作的示例实际上是在SQLDataAccess的Objective-C版本中。
SQLDataAccess是一个非常快速和高效的类,可以用来代替CoreData,它实际上只使用SQLite作为底层数据 存储没有CoreData附带的所有CoreData核心数据完整性故障崩溃。
答案 11 :(得分:0)
到目前为止,这是我在Swift中使用过的最好的Sqlite库:https://github.com/stephencelis/SQLite.swift
查看代码示例。比C API干净得多:
import SQLite
let db = try Connection("path/to/db.sqlite3")
let users = Table("users")
let id = Expression<Int64>("id")
let name = Expression<String?>("name")
let email = Expression<String>("email")
try db.run(users.create { t in
t.column(id, primaryKey: true)
t.column(name)
t.column(email, unique: true)
})
// CREATE TABLE "users" (
// "id" INTEGER PRIMARY KEY NOT NULL,
// "name" TEXT,
// "email" TEXT NOT NULL UNIQUE
// )
let insert = users.insert(name <- "Alice", email <- "alice@mac.com")
let rowid = try db.run(insert)
// INSERT INTO "users" ("name", "email") VALUES ('Alice', 'alice@mac.com')
for user in try db.prepare(users) {
print("id: \(user[id]), name: \(user[name]), email: \(user[email])")
// id: 1, name: Optional("Alice"), email: alice@mac.com
}
// SELECT * FROM "users"
let alice = users.filter(id == rowid)
try db.run(alice.update(email <- email.replace("mac.com", with: "me.com")))
// UPDATE "users" SET "email" = replace("email", 'mac.com', 'me.com')
// WHERE ("id" = 1)
try db.run(alice.delete())
// DELETE FROM "users" WHERE ("id" = 1)
try db.scalar(users.count) // 0
// SELECT count(*) FROM "users"
文档还指出“ SQLite.swift还可以作为C API的轻量级,对Swift友好的包装器”,并附带一些示例。