Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách truy xuất SQLite database trên iPhone bằng Swift

Lưu trữ dữ liệu là yếu tố quan trọng khi thiết kế ứng dụng. SQLite là một hệ quản trị cơ sở dữ liệu quan hệ nhẹ, nhúng trong thư viện C, phù hợp cho lưu trữ cục bộ trên iOS.

Bài viết hướng dẫn cách truy xuất SQLite đơn giản nhất bằng Swift, tạo app demo: nhập tên → lưu vào DB → hiển thị danh sách.

Các bước thực hiện

Bước 1: Tạo dự án

Xcode → Single View App → Tên: "DBSqlite".

Bước 2: Thiết kế UI

Mở Main.storyboard → Thêm:

  • 1 UITextField (nhập tên)
  • 2 UIButton: "Insert" (lưu) và "Show Data" (hiển thị)

Tạo @IBOutlet cho text field (nameTextField), @IBAction cho 2 button (btnInsert, btnShowData).

Cách truy xuất SQLite database trên iPhone bằng Swift

Bước 3: Import SQLite3 và tạo kết nối

import UIKit
import SQLite3

class ViewController: UIViewController {
    
    @IBOutlet weak var nameTextField: UITextField!
    var db: OpaquePointer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 1. Tạo đường dẫn file .sqlite trong Document Directory
        let fileURL = try! FileManager.default
            .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("user_name.sqlite")
        
        print("SQLite path: \(fileURL.path)") // Debug: in ra đường dẫn file
        
        // 2. Mở database
        if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
            print("Lỗi mở database")
            return
        }
        
        // 3. Tạo bảng nếu chưa tồn tại
        let createTableQuery = """
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT
            )
        """
        
        if sqlite3_exec(db, createTableQuery, nil, nil, nil) != SQLITE_OK {
            let errorMsg = String(cString: sqlite3_errmsg(db)!)
            print("Lỗi tạo bảng: \(errorMsg)")
        }
    }

Bước 4: Chèn dữ liệu (Insert)

@IBAction func btnInsert(_ sender: Any) {
    guard let userName = nameTextField.text, !userName.isEmpty else { return }
    
    var statement: OpaquePointer?
    let query = "INSERT INTO users (name) VALUES (?)"
    
    // 1. Prepare statement
    if sqlite3_prepare_v2(db, query, -1, &statement, nil) != SQLITE_OK {
        let errMsg = String(cString: sqlite3_errmsg(db)!)
        print("Lỗi prepare insert: \(errMsg)")
        return
    }
    
    // 2. Bind tham số
    if sqlite3_bind_text(statement, 1, (userName as NSString).utf8String, -1, nil) != SQLITE_OK {
        let errMsg = String(cString: sqlite3_errmsg(db)!)
        print("Lỗi bind text: \(errMsg)")
        return
    }
    
    // 3. Thực thi
    if sqlite3_step(statement) != SQLITE_DONE {
        let errMsg = String(cString: sqlite3_errmsg(db)!)
        print("Lỗi insert: \(errMsg)")
    } else {
        print("Đã lưu: \(userName)")
        nameTextField.text = ""
    }
    
    // 4. Finalize
    sqlite3_finalize(statement)
}

Bước 5: Truy vấn dữ liệu (Select)

@IBAction func btnShowData(_ sender: Any) {
    let query = "SELECT * FROM users"
    var statement: OpaquePointer?
    
    if sqlite3_prepare_v2(db, query, -1, &statement, nil) != SQLITE_OK {
        let errMsg = String(cString: sqlite3_errmsg(db)!)
        print("Lỗi prepare select: \(errMsg)")
        return
    }
    
    print("=== Danh sách users ===")
    while sqlite3_step(statement) == SQLITE_ROW {
        // Cột 0: id, Cột 1: name
        let id = sqlite3_column_int(statement, 0)
        let name = String(cString: sqlite3_column_text(statement, 1))
        print("ID: \(id), Name: \(name)")
    }
    
    sqlite3_finalize(statement)
}

Bước 6: Đóng database khi không dùng (AppDelegate)

// AppDelegate.swift
func applicationWillTerminate(_ application: UIApplication) {
    if let db = (window?.rootViewController as? ViewController)?.db {
        sqlite3_close(db)
    }
}

Mã hoàn chỉnh ViewController.swift

import UIKit
import SQLite3

class ViewController: UIViewController {
    
    @IBOutlet weak var nameTextField: UITextField!
    var db: OpaquePointer?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let fileURL = try! FileManager.default
            .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
            .appendingPathComponent("user_name.sqlite")
        
        print("DB Path: \(fileURL.path)")
        
        if sqlite3_open(fileURL.path, &db) != SQLITE_OK {
            print("Lỗi mở DB")
            return
        }
        
        let createTable = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)"
        if sqlite3_exec(db, createTable, nil, nil, nil) != SQLITE_OK {
            let err = String(cString: sqlite3_errmsg(db)!)
            print("Lỗi tạo bảng: \(err)")
        }
    }
    
    @IBAction func btnInsert(_ sender: Any) {
        guard let name = nameTextField.text, !name.isEmpty else { return }
        var stmt: OpaquePointer?
        let sql = "INSERT INTO users (name) VALUES (?)"
        
        if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK {
            sqlite3_bind_text(stmt, 1, (name as NSString).utf8String, -1, nil)
            if sqlite3_step(stmt) == SQLITE_DONE {
                print("Đã lưu: \(name)")
                nameTextField.text = ""
            }
        }
        sqlite3_finalize(stmt)
    }
    
    @IBAction func btnShowData(_ sender: Any) {
        var stmt: OpaquePointer?
        let sql = "SELECT * FROM users"
        
        if sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK {
            while sqlite3_step(stmt) == SQLITE_ROW {
                let id = sqlite3_column_int(stmt, 0)
                let name = String(cString: sqlite3_column_text(stmt, 1))
                print("ID: \(id), Name: \(name)")
            }
        }
        sqlite3_finalize(stmt)
    }
    
    deinit {
        sqlite3_close(db)
    }
}

Kiểm tra file SQLite

Chạy app → Nhập tên → Bấm Insert → Bấm Show Data → Xem console in ra kết quả.

Để xem file DB trực tiếp: Mở Terminal → sqlite3 /path/to/user_name.sqlite → .tables → SELECT * FROM users;

Cách truy xuất SQLite database trên iPhone bằng Swift

Cách truy xuất SQLite database trên iPhone bằng Swift

Thư viện khuyến nghị cho Production

  • GRDB.swift: Type-safe, Swift-friendly, hỗ trợ migration, observation
  • SQLite.swift: Wrapper nhẹ, expressive API
  • Realm: Không phải SQLite nhưng phổ biến, dễ dùng hơn

Lưu ý: SQLite3 API là C API, cần quản lý bộ nhớ thủ công (prepare/bind/step/finalize). Thư viện wrapper giúp an toàn và ngắn gọn hơn.