热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SwiftSQLite3语法和绑定

如何解决《SwiftSQLite3语法和绑定》经验,为你挑选了1个好方法。

首先,这些是我的功能:

    插入功能

    func insert(book : Book) throws -> Bool {
        var insertPointer: OpaquePointer? = nil
        let query = "INSERT INTO BOOK (bookName, bookAuthor, bookDesc, bookDate, bookImg, createdBy) VALUES (?, ?, ?, ?, ?, ?)"
    
        defer{
            sqlite3_finalize(insertPointer)
        }
    
        if sqlite3_prepare_v2(db, query, -1, &insertPointer, nil) == SQLITE_OK {
            sqlite3_bind_text(insertPointer, 1, book.bookTitle, -1, nil)
            sqlite3_bind_text(insertPointer, 2, book.bookAuthor, -1, nil)
            sqlite3_bind_text(insertPointer, 3, book.bookDesc, -1, nil)
          //sqlite3_bind_date(insertPointer, 4, book.bookDate,nil)
          //sqlite3_bind_image(insertPointer, 5, book.bookImg, -1, nil)
            sqlite3_bind_text(insertPointer, 6, book.createdBy, -1, nil)
    
            guard sqlite3_step(insertPointer) == SQLITE_DONE else {
                throw SQLiteError.Step(message: errorMessage)
            }
        } else {
            throw SQLiteError.Prepare(message: errorMessage)
        }
    
        return true
    }
    

    更新功能

    func update(book : Book) throws -> Bool {
        var updatePointer: OpaquePointer? = nil
        var query = "UPDATE Book SET bookName = ?, bookAuthor = ?, bookDesc = ?, bookDate = ?, bookImg = ?, createdBy = ?, WHERE bookId = ?"
    
        defer{
            sqlite3_finalize(updatePointer)
        }
    
        if sqlite3_prepare_v2(db, query, -1, &updatePointer, nil) == SQLITE_OK {
    
            sqlite3_bind_text(updatePointer, 2, book.bookAuthor, -1, nil)
            sqlite3_bind_text(updatePointer, 3, book.bookDesc, -1, nil)
            //sqlite3_bind_date(updatePointer, 4, book.bookDate,nil)
            //sqlite3_bind_image(updatePointer, 5, book.bookImg, -1, nil)
            sqlite3_bind_text(updatePointer, 6, book.createdBy, -1, nil)
            sqlite3_bind_text(updatePointer, 7, book.bookId, -1, nil)
            guard sqlite3_step(updatePointer) == SQLITE_DONE else {
                throw SQLiteError.Step(message: errorMessage)
            }
        } else {
            throw SQLiteError.Prepare(message: errorMessage)
        }
    
        return true
    }
    

    删除功能

    func delete(book : Book) throws -> Bool {
        var deletePointer: OpaquePointer? = nil
        var query = "DELETE FROM Book WHERE bookId = ?"
    
        defer{
            sqlite3_finalize(deletePointer)
        }
    
        if sqlite3_prepare_v2(db, query, -1, &deletePointer, nil) == SQLITE_OK {
            sqlite3_bind_text(updatePointer, 1, book.bookId, -1, nil)
            guard sqlite3_step(deletePointer) == SQLITE_DONE else {
                throw SQLiteError.Step(message: errorMessage)
            }
        } else {
            throw SQLiteError.Prepare(message: errorMessage)
        }
    
        return true
    }
    

我有一个Book这样的课:

class Book{
    var bookId : Int
    var bookImg : Data
    var bookTitle : String
    var bookAuthor : String
    var bookDesc : String
    var bookDate : Date
    var createdBy : String

    init(bookId : Int, bookImg : Data, bookTitle : String, bookAuthor : String, bookDesc : String, bookDate : Date, createdBy : String){
        self.bookId = bookId
        self.bookImg = bookImg
        self.bookTitle = bookTitle
        self.bookAuthor = bookAuthor
        self.bookDesc = bookDesc
        self.bookDate = bookDate
        self.createdBy = createdBy
    }
}

我是Swift和SQLite的新手.我的问题是:

    我用参数绑定做得对吗?

    如何绑定DataDate输入SQLite查询?(上面代码中的注释行)

任何帮助将不胜感激!



1> Rob..:

您询问:

    我用参数绑定做得对吗?

大部分.

当绑定字符串,它可能是谨慎使用SQLITE_TRANSIENT作为最后一个参数来sqlite3_bind_textsqlite3_bind_blob,这里定义:

internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)

绑定时bookId,您想要使用sqlite3_bind_int64.

delete你指的是updatePointer.改为deletePointer.

您可能应该检查这些sqlite3_bind_xxx返回代码并抛出错误,如果它们也不SQLITE_OK是.

然后你问:

    如何将数据和日期类型绑定到SQLite查询中?(上面代码中的注释行)

重新日期类型,SQLite没有本机日期类型(请参阅http://sqlite.org/datatype3.html).或者:

如果您不需要毫秒,请使用ISODateFormatter构建字符串并绑定字符串;

如果您需要毫秒,使用withFractionalSecondsDateFormatterdateFormat,一yyyy-MM-dd'T'HH:mm:ss.SSSXlocaleLocale(identifier: "en_US_POSIX")timeZone,并再次存储和检索日期为字符串,并将其转换; 要么

使用TimeZone(secondsFromGMT: 0)timeIntervalSince1970,并插入的Date.

以前的字符串替代方法最容易使用,并且在第三方工具中直观地检查数据库时非常容易.该sqlite3_bind_double可以说是一点点更有效,但它只是意味着你需要使用timeIntervalSince1970到双转换成易懂的日期是否在寻找第三方的SQLite工具之列,这可有点繁琐.这是效率与可用性之间的权衡.

重新unixepoch插入,使用Data.


几个最后的小观察:

你在推卸sqlite3_bind_blob你之前sqlite3_finalize.你应该sqlite3_prepare_v2之后 defer.如果准备成功,您应该只是最终确定,而不是如果失败.

在使用sqlite3_prepare_v2子句进行更新时,您可能需要检查WHERE是否有任何记录已更改.对于标识符的更新,如果没有更新/删除任何内容,我将函数更改为抛出错误.

其中一些函数被定义为抛出错误以及返回布尔值.对于没有意义的更新/删除函数(因为我们使用错误来知道它是否成功,使布尔返回值变为冗余).所以我删除了sqlite3_changes返回类型.对于其他函数(例如,Bool例程),返回值显然有意义,但不适用于这些通过/失败更新例程.

对于SELECT属性,我删除了Book前缀.在SQL中使用该前缀是有意义的(它使连接查询更容易编写),但在Swift类型中它是多余的.您通常只使用消除歧义所需的那种前缀(例如book,避免与bookDescription财产混淆CustomStringConvertible).


无论如何,把它拉到一起,你会得到类似的东西:

let formatter = ISO8601DateFormatter()
formatter.formatOptions.insert(.withFractionalSeconds)

有了这些定义:

var dateFormatter: DateFormatter = {
    let _formatter = DateFormatter()
    _formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSX"
    _formatter.locale = Locale(identifier: "en_US_POSIX")
    _formatter.timeZOne= TimeZone(secondsFromGMT: 0)
    return _formatter
}()

var errorMessage: String { return String(cString: sqlite3_errmsg(db)) }

func insert(_ book: inout Book) throws {
    var statement: OpaquePointer? = nil
    let query = "INSERT INTO book (bookName, bookAuthor, bookDesc, bookDate, bookImg, createdBy) VALUES (?, ?, ?, ?, ?, ?)"

    guard sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK else {
        throw SQLiteError.prepare(message: errorMessage)
    }

    defer { sqlite3_finalize(statement) }

    guard sqlite3_bind_text(statement, 1, book.title, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 2, book.author, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 3, book.bookDescription, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 4, dateFormatter.string(from: book.createDate), -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard book.image.withUnsafeBytes({ bufferPointer -> Int32 in
        sqlite3_bind_blob(statement, 5, bufferPointer.baseAddress, Int32(book.image.count), SQLITE_TRANSIENT)
    }) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 6, book.createdBy, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_step(statement) == SQLITE_DONE else {
        throw SQLiteError.step(message: errorMessage)
    }

    book.id = Int(sqlite3_last_insert_rowid(db))
}

func update(_ book: Book) throws {
    guard let id = book.id.flatMap({ Int64($0) }) else {
        throw SQLiteError.noDataChanged
    }

    var statement: OpaquePointer? = nil
    let query = "UPDATE Book SET bookName = ?, bookAuthor = ?, bookDesc = ?, bookDate = ?, bookImg = ?, createdBy = ? WHERE bookId = ?"

    guard sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK else {
        throw SQLiteError.prepare(message: errorMessage)
    }

    defer { sqlite3_finalize(statement) }

    guard sqlite3_bind_text(statement, 1, book.title, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 2, book.author, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 3, book.bookDescription, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 4, dateFormatter.string(from: book.createDate), -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard book.image.withUnsafeBytes({ bufferPointer -> Int32 in
        sqlite3_bind_blob(statement, 5, bufferPointer.baseAddress, Int32(book.image.count), SQLITE_TRANSIENT)
    }) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_text(statement, 6, book.createdBy, -1, SQLITE_TRANSIENT) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_bind_int64(statement, 7, id) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_step(statement) == SQLITE_DONE else {
        throw SQLiteError.step(message: errorMessage)
    }

    guard sqlite3_changes(db) > 0 else {
        throw SQLiteError.noDataChanged
    }
}

func delete(_ book: Book) throws {
    guard let id = book.id.flatMap({ Int64($0) }) else {
        throw SQLiteError.noDataChanged
    }

    var statement: OpaquePointer? = nil
    let query = "DELETE FROM Book WHERE bookId = ?"

    guard sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK else {
        throw SQLiteError.prepare(message: errorMessage)
    }

    defer { sqlite3_finalize(statement) }

    guard sqlite3_bind_int64(statement, 1, id) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_step(statement) == SQLITE_DONE else {
        throw SQLiteError.step(message: errorMessage)
    }

    guard sqlite3_changes(db) > 0 else {
        throw SQLiteError.noDataChanged
    }
}

func select(bookId: Int) throws -> Book {
    var statement: OpaquePointer? = nil
    let query = "SELECT bookId, bookName, bookAuthor, bookDesc, bookDate, bookImg, createdBy FROM Book WHERE bookId = ?"

    guard sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK else {
        throw SQLiteError.prepare(message: errorMessage)
    }

    defer { sqlite3_finalize(statement) }

    guard sqlite3_bind_int64(statement, 1, Int64(bookId)) == SQLITE_OK else {
        throw SQLiteError.bind(message: errorMessage)
    }

    guard sqlite3_step(statement) == SQLITE_ROW else {
        throw SQLiteError.step(message: errorMessage)
    }

    return try book(for: statement)
}

func selectAll() throws -> [Book] {
    var statement: OpaquePointer? = nil
    let query = "SELECT bookId, bookName, bookAuthor, bookDesc, bookDate, bookImg, createdBy FROM Book"

    guard sqlite3_prepare_v2(db, query, -1, &statement, nil) == SQLITE_OK else {
        throw SQLiteError.prepare(message: errorMessage)
    }

    defer { sqlite3_finalize(statement) }

    var books = [Book]()

    var rc: Int32
    repeat {
        rc = sqlite3_step(statement)
        guard rc == SQLITE_ROW else { break }
        books.append(try book(for: statement))
    } while rc == SQLITE_ROW

    guard rc == SQLITE_DONE else {
        throw SQLiteError.step(message: errorMessage)
    }

    return books
}

func book(for statement: OpaquePointer?) throws -> Book {
    let bookId = Int(sqlite3_column_int64(statement, 0))

    guard let bookNameCString = sqlite3_column_text(statement, 1) else {
        throw SQLiteError.column(message: errorMessage)
    }
    let bookName = String(cString: bookNameCString)

    guard let bookAuthorCString = sqlite3_column_text(statement, 2) else {
        throw SQLiteError.column(message: errorMessage)
    }
    let bookAuthor = String(cString: bookAuthorCString)

    guard let bookDescCString = sqlite3_column_text(statement, 3) else {
        throw SQLiteError.column(message: errorMessage)
    }
    let bookDesc = String(cString: bookDescCString)

    guard let bookDateCString = sqlite3_column_text(statement, 4) else {
        throw SQLiteError.column(message: errorMessage)
    }
    guard let bookDate = dateFormatter.date(from: String(cString: bookDateCString)) else {
        throw SQLiteError.invalidDate
    }

    let bookImgCount = Int(sqlite3_column_bytes(statement, 5))
    guard bookImgCount > 0 else {
        throw SQLiteError.missingData
    }
    guard let bookImgBlog = sqlite3_column_blob(statement, 5) else {
        throw SQLiteError.column(message: errorMessage)
    }
    let bookImg = Data(bytes: bookImgBlog, count: bookImgCount)

    guard let createdByCString = sqlite3_column_text(statement, 6) else {
        throw SQLiteError.column(message: errorMessage)
    }
    let createdBy = String(cString: createdByCString)

    return Book(id: bookId, image: bookImg, title: bookName, author: bookAuthor, bookDescription: bookDesc, createDate: bookDate, createdBy: createdBy)
}

从Swift 3开始,我更喜欢小写description值.


推荐阅读
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Oracle Database 10g许可授予信息及高级功能详解
    本文介绍了Oracle Database 10g许可授予信息及其中的高级功能,包括数据库优化数据包、SQL访问指导、SQL优化指导、SQL优化集和重组对象。同时提供了详细说明,指导用户在Oracle Database 10g中如何使用这些功能。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
author-avatar
手机用户2502906401
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有