当前位置:网站首页>Use SQLite provided by the system
Use SQLite provided by the system
2022-07-24 23:27:00 【Hanyang Li】
1. Add to the project libsqlite3.tbd library , Click item , choice TARGETS Medium project , stay Frameworks,libraries,and Embedded Content In the options Click on +, Search libsqlite3, Select and add libsqlite3.tbd.
2. libsqlite3 It uses OC To write , You need to create an overseas connection file SQLite-Bridge.h, Project configuration bridging file Project name / file name (SQLite-Bridge.h), Reference header file ,
//
// SQLite-Bridge.h
//
#import <sqlite3.h>3. establish SQLite Manager SQLiteManager.swift
//
// SQLiteManager.swift
//
import Foundation
///SQLite Manager
/**
- SQLite The frame is pure C The framework of language
- All functions are based on sqlite3_ At the beginning
*/
class SQLiteManager {
/// Single case
static let sharedManager = SQLiteManager()
// Global database operation handle
var db: OpaquePointer? = nil
/// Open database
/// - Parameter dbName: Database name
func openDB(dbName: String){
var path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
path = (path as NSString).appendingPathComponent(dbName)
print(path)
/**
Parameters
1. The full path of the database CChar C Language string
2. Global database access ‘ Handle ’ -> The pointer , All subsequent operations on the database , All based on this handle
Return value If == SQLITE_OK It means success
If the database doesn't exist , Will create database , Then open the database
If the data exists , Will directly open the database
*/
if sqlite3_open(path, &db) != SQLITE_OK {
print(" Failed to open database ")
return
}
if createTable1(){
print(" Data table created successfully ")
}else{
print(" Failed to create data table ")
}
}
//MARK: - Data query operation
/// perform SQL Returns the data result set
/// - Parameter sql: sql
func execRecordSet(sql: String) -> [[String: Any]]?{
//1. precompile SQL
/**
Parameters
1. Global database handle
2. To execute SQL Of C Language string
3. To execute SQL The length in bytes of , however , If you pass in -1, SQLite The frame will automatically calculate
4. STMT - Precompiled instruction handle
-- Follow up on ‘ This query ’ All operations , All based on this handle
-- What must be paid attention to , Handle must be released
-- After compilation , It can be understood as a temporary data set , adopt step function , Be able to get the results in sequence
5. About STMT Pointer to tail parameter , It's usually passed in nil
Return value
If the compilation is successful , Express SQL Be able to perform normally , return SQLITE_OK
*/
var stmt: OpaquePointer? = nil
if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) != SQLITE_OK {
print("SQL error ")
// Release
sqlite3_finalize(stmt)
return nil
}
// Create an array of dictionaries
var result = [[String: Any]]()
// Single step execution to get results - ROW Corresponding to a complete record
while sqlite3_step(stmt) == SQLITE_ROW {
// Add dictionary records to the array
result.append(record(stmt: stmt!))
}
//print(result)
// Release stmt
sqlite3_finalize(stmt)
// Return results
return result
}
/// from stmt Get the current record content
/**
Tips : When obtaining the complete information of a record , All functions start with sqlite3_column_
*/
private func record(stmt: OpaquePointer) -> [String: Any]{
//1. Know the number of columns of records
let cols = sqlite3_column_count(stmt)
//2. Create a dictionary for a single record
var row = [String: Any]()
//3. Cycle each column , Get the corresponding content of each column
for col in 0..<cols{
//1> Name
let cName = sqlite3_column_name(stmt, col)
let name = String(cString: cName!, encoding: .utf8)
//2> data type
let type = sqlite3_column_type(stmt, col)
var value: Any?
switch type {
case SQLITE_FLOAT: // decimal
value = sqlite3_column_double(stmt, col)
case SQLITE_INTEGER: // Integers
value = Int(sqlite3_column_int64(stmt, col))
case SQLITE_TEXT:
// Record C Language characters this time
value = String(cString: sqlite3_column_text(stmt, col)!)
case SQLITE_NULL: // Null value , Generally, the fields allowed in the database are nil, however OC The dictionary of cannot be inserted nil
value = NSNull() //NSNull It is specially used to insert control into dictionaries and arrays
default:
print(" Unsupported data type ")
}
//print("\(name) --- \(type) --- \(value)")
// Get a content , Set up a dictionary
row[name!] = value
}
//print(row)
return row
}
//MARK: - Data manipulation functions
/// perform SQL to update / Delete data
/// - Parameter sql: sql
/// - Returns: Return the number of modified data rows
func execUpdate(sql: String) -> Int{
//1. perform SQL - If SQL The error will return -1
if !execSQL(sql: sql){
// Execution failure return -1
return -1
}
//2. Successful implementation , Returns the number of data rows affected
return Int(sqlite3_changes(db))
}
/// perform SQL insert data
/// - Parameter sql: sql
/// - Returns: Return to automatically increased id
func execInsert(sql: String) -> Int{
//1. perform SQL
if !execSQL(sql: sql){
// Execution failure return -1
return -1
}
//2. Successful implementation , Return to automatically increased id
return Int(sqlite3_last_insert_rowid(db))
}
/// perform SQL Instructions
/// - Parameter sql: sql
/// - Returns: Whether the return is correct
func execSQL(sql: String) -> Bool{
/**
Parameters
1. Database global handle
2. Executes SQL
3.callback, Execution completed SQL after , Called C Language function pointer , It's usually passed in nil
4. The third parameter callback, Address of function parameter , It's usually passed in nil
5. error message , There are other ways to get execution , It's usually passed in nil
Return value If == SQLITE_OK It means success
*/
return sqlite3_exec(db, sql, nil, nil, nil) == SQLITE_OK
}
//MARK: - Create data table
// Development process ,SQL Statements are prone to problems
// Maybe sql Output , With the help of navicat Shop for grammar check
//2. When splicing strings , Add... At the end \n You can avoid splicing strings , Cause string connection error
// Best to add \n
private func createTable() -> Bool{
//1. Get ready SQL
let sql = "CREATE TABLE IF NOT EXISTS 'T_Person' ( \n" +
"'id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, \n" +
"'name' TEXT, \n" +
"'age' INTEGER, \n" +
"'height' NUMBER, \n" +
"'title' TEXT \n" +
");"
//print(sql)
return execSQL(sql: sql)
}
//MARK: - Create data table
/// Create data table - Business applications The mainstream approach
/// - Returns: The success of
private func createTable1() -> Bool{
//1. from bundle Load in sql file
let path = Bundle.main.path(forResource: "db.sql", ofType: nil)!
//2. Read SQL String
let sql = try! String(contentsOfFile: path)
//3. perform sql
//print(sql)
return execSQL(sql: sql)
}
}4. establish db.sql file
-- Create a personal table --
CREATE TABLE IF NOT EXISTS "T_Person" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT,
"age" INTEGER,
"height" NUMBER
);
-- Create a book table --
CREATE TABLE IF NOT EXISTS "T_Book" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"bookName" TEXT
);5. Create model file Person.swift
//
// Person.swift
//
import UIKit
class Person: NSObject {
@objc var id = 0
@objc var name: String?
@objc var age = 0
@objc var height:Double = 0
init(dict: [String: Any]){
super.init()
setValuesForKeys(dict)
}
override func setValue(_ value: Any?, forUndefinedKey key: String) {
}
override var description: String{
let keys = ["id", "name", "age", "height"]
return dictionaryWithValues(forKeys: keys).description
}
//MARK: - Database query
class func persons() -> [Person]? {
//1. Get ready SQL
let sql = "SELECT id, name, age, height FROM T_Person;"
//2. perform SQL -> Dictionary to array
guard let array = SQLiteManager.sharedManager.execRecordSet(sql: sql) else{
return nil
}
//3. Ergodic dictionary , Dictionary to model
var arrayM = [Person]()
for dict in array {
arrayM.append(Person(dict: dict))
}
return arrayM
}
//MARK: - Database operation
/// Put the current object id The corresponding data is deleted
func deletePerson() -> Bool{
//1. Get ready SQL
let sql = "DElETE FROM T_Person WHERE id = \(id);"
//2. perform SQL - Record the number of rows affected
let row = SQLiteManager.sharedManager.execUpdate(sql: sql)
print(" Number of rows that affect data \(row)")
return row>0
}
/// Put the current object id Modify the corresponding data
func updatePerson() -> Bool{
//1. Get ready SQL
let sql = "UPDATE T_Person SET name = '\(name!)', age = \(age), height = \(height) \n" +
"WHERE id = \(id);"
//2. perform SQL - Record the number of rows affected
let row = SQLiteManager.sharedManager.execUpdate(sql: sql)
return row > 0
}
/// Add the current object to the database
func insertPerson() -> Bool{
//1. Get ready SQL
let sql = "INSERT INTO T_Person (name, age, height) VALUES ('\(name ?? "")', \(age), \(height));"
//2. perform SQL
id = SQLiteManager.sharedManager.execInsert(sql: sql)
return id > 0
}
}6. The test method
6.1 Open the database and create a table , stay SceneDelegate.swift Method execution
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else { return }
// Persistent connections [ Network long connection - im ]
// Only open the database , Do not close the database !
// For subsequent reuse , Read and write directly ! More efficient ! Mobile development database , Usually persistent connections !
SQLiteManager.sharedManager.openDB(dbName: "demo.db")
}6.2 SQLite Basic operation
//
// ViewController.swift
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//demoInsert()
//demoUpdate()
//demoDelete()
//print((Person.persons() ?? []) as NSArray)
//manyPersons2()
manyPersons4()
}
/// Failure in development
func manyPersons4(){
// Take the function of absolute time
//CFAbsoluteTimeGetCurrent() - Will receive ‘ system service ’ Influence , During the performance test , There may be errors !
//CACurrentMediaTime() - It's only about hardware time , Performance testing is more accurate
//1. Starting time
let start = CACurrentMediaTime()
// Open transaction
SQLiteManager.sharedManager.execSQL(sql: "BEGIN TRANSACTION;")
for i in 0..<10000{
let p = Person(dict: ["name": " Zhang San -\(i)", "age": 22, "height": 1.8 ])
/// Insert the failure
if !p.insertPerson(){
// Roll back the transaction
SQLiteManager.sharedManager.execSQL(sql: "ROLLBACK TRANSACTION;")
break
}
}
// Submit things
SQLiteManager.sharedManager.execSQL(sql: "COMMIT TRANSACTION;")
//2. End time
print(" complete \(CACurrentMediaTime() - start)")
}
/// Simulation failed
func manyPersons3(){
//1. Starting time
let start = CACurrentMediaTime()
// Open transaction
SQLiteManager.sharedManager.execSQL(sql: "BEGIN TRANSACTION;")
for i in 0..<10000{
Person(dict: ["name": " Zhang San -\(i)", "age": 22, "height": 1.8 ]).insertPerson()
if i==1000 { //
// Roll back the transaction
SQLiteManager.sharedManager.execSQL(sql: "ROLLBACK TRANSACTION;")
break
}
}
// Submit things
SQLiteManager.sharedManager.execSQL(sql: "COMMIT TRANSACTION;")
//2. End time
print(" complete \(CACurrentMediaTime() - start)")
}
/**
Business
1. stay SQLite Database operation , If “ Not explicitly ” Open transaction , Every database operation instruction will start a transaction , After execution , Commit transaction
2. If Explicit Open transaction of , SQLite No longer open transactions
*/
// Insert a lot of data - Using transactions only requires 0.7s
func manyPersons2(){
//1. Starting time
let start = CACurrentMediaTime()
// Open transaction
SQLiteManager.sharedManager.execSQL(sql: "BEGIN TRANSACTION;")
for i in 0..<10000{
Person(dict: ["name": " Zhang San -\(i)", "age": 22, "height": 1.8 ]).insertPerson()
}
// Submit things
SQLiteManager.sharedManager.execSQL(sql: "COMMIT TRANSACTION;")
//2. End time
print(" complete \(CACurrentMediaTime() - start)")
}
// Insert a lot of data 7 second
func manyPersons1(){
//1. Starting time
let start = CACurrentMediaTime()
for i in 0..<10000{
Person(dict: ["name": " Zhang San -\(i)", "age": 22, "height": 1.8 ]).insertPerson()
}
//2. End time
print(" complete \(CACurrentMediaTime() - start)")
}
// Delete operation
func demoDelete(){
let p = Person(dict: ["id": 2])
if p.deletePerson(){
print(" Delete successful \(p)")
}else{
print(" Delete failed ")
}
}
// Modify the operating
func demoUpdate(){
let p = Person(dict: ["id": 1, "name": " Smile ", "age": 17, "height": 1.68 ])
if p.updatePerson(){
print(" Modification successful \(p)")
}else{
print(" Modification failed ")
}
}
// The insert
func demoInsert(){
let p = Person(dict: ["name": " Zhang San ", "age": 22, "height": 1.8 ])
if p.insertPerson(){
print(" Insert the success \(p)")
}else{
print(" Insert the failure ")
}
}
}边栏推荐
- How to speculate on the Internet? Is it safe to speculate on mobile phones
- 解决JSP无法使用session.getAttribute()
- Power consumption of chip
- 物联网平台返回数据解析时遇到org.json.JSONException: No value for Value怎么办
- The rule created by outlook mail is invalid. Possible reasons
- Do you need to open an account to buy a wealth management product with a 6% income?
- Network Security Learning (IV) user and group management, NTFS
- 激光雷达障碍物检测与追踪实战——cuda版欧式聚类
- 买收益百分之6的理财产品,需要开户吗?
- Okaleido tiger NFT is about to log in to binance NFT platform, and the future market continues to be optimistic
猜你喜欢

Go基础笔记_4_map

First engineering practice, or first engineering thought—— An undergraduate's perception from learning oi to learning development

Convert a string to an integer and don't double it

NVIDA-TensorRT部署(一)

JS ------ Chapter 3 JS cycle

ShardingSphere-数据库分库分表简介

Horizontally centered element

Zheng Huijuan: Research on application scenarios and evaluation methods of data assets based on the unified market

Development direction and problems of optaplanner

Nvida tensorrt deployment (I)
随机推荐
Mandatory interview questions: 1. shallow copy and deep copy_ Deep copy
Notes of Teacher Li Hongyi's 2020 in-depth learning series 9
The size of STM32 stack
On the open and closed principle
Entity service is an anti pattern
Bug summary
In pgplsql: = and=
Org.json Jsonexception: what about no value for value
Js----- Chapter 4 array
HLS编程入门
Notes of Teacher Li Hongyi's 2020 in-depth learning series 4
Effect evaluation of generative countermeasure network
Browser cache
基于Verilog HDL的数字秒表
RichTextBox save as picture
Let‘s Encrypt
谢振东:公共交通行业数字化转型升级的探索与实践
With screen and nohup running, there is no need to worry about deep learning code anymore | exiting the terminal will not affect the operation of server program code
Solve the problem that JSP cannot use session.getattribute()
Go基础笔记_4_map