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

SQLite入门教程

原文:SQLiteTutorial:GettingStarted注意:在2016-04-06已经更新到Xcode7.3iOS9.3和Swift2.2。在软件开发的世界中,在你需要对

原文:SQLite Tutorial: Getting Started

注意:在2016-04-06已经更新到 Xcode 7.3 iOS 9.3Swift 2.2

在软件开发的世界中,在你需要对你的 app 进行数据持久化前开发它并不用花费很多时间。在许多情况下,这是以数据结构的形式出现的,但你如何更有效地存储它?

幸运的是,一些伟大的先行者已经开发了关于访问存储在数据库中的结构化数据和写入语言的功能的解决方案。这个 SQLite 教程向您展示了如何快速使用 Swift 在流行平台工作上使用 SQLite 数据库,在 iOS 平台 SQLite 是默认可用的。如果你熟悉 Core Data 的话,你就会知道 SQLite 一些和 Core Data 类似的最常见持久化对象图的方法。

在本SQLite的教程中,您将学习到以下几种如何执行数据库的操作:

  • 创建和连接一个数据库
  • 创建一个表
  • 插入行
  • 更新行
  • 删除行
  • 查询数据库
  • 处理 SQLite 错误

在学完这些基本的如何执行操作后,你会看到如何用一种更加 Swift 的方式将它们包装起来。它会帮助在你的应用中写更加抽象 APIs ,这样的话就可以大量的避免直接面对 SQLite 中的C语言的 APIs

最后,我将简单介绍流行的开源资源 Swift 封装的 SQLite.swift 的底层框架内是如何工作的。

Note: 数据库,甚至是SQLite自身,是巨大的主题,所以它们的很多内容超出了本教程的范围。本文假定你对于关系数据库的思想有基本的了解,你主要是来学习如何结合Swift来使用SQLite。

开始

下载这个 SQLite 教程的 启动项目 ,打开 SQLiteTutorial.xcworkspace。根据项目的导航栏打开 Tutorial.playground。你会马上注意到 import SQLite 那行有一个错误信息,你至少要编译项目一次,可以使用 Command + B 。这是因为需要工作空间的配置信息来创建一个模块,这样SQLite才可以运行在 playground

Note: SQLite是不正确的模块,你不能在你的项目中调用导入SQLite模块,不要被 import SQLite 这行误导;相反,你可以使用一个桥接的头部。

playground 打开的时候,设置它为手动运行,而不是自动运行:

《SQLite 入门教程》 sqliteswift_manually_run_payground.png

这将有助于确保按你想那样运行SQL命令。

在这个页面的顶部你也可以看到一个 destroyPart1Database() 函数的调用;你可以安全地忽略这个,由于每次运行 playground 时,数据库文件会被破坏。这将确保你在这个SQLite教程所有语句成功执行。

你的 playground 的文件系统中,在需要的地方写SQLite数据库文件。可以在终端中运行下面的命令,为您的 playground 创建数据目录:

mkdir -p ~/Documents/Shared\ Playground\ Data/SQLiteTutorial

我为什么要选择SQLite?

对的,在iOS中 SQLite 不是唯一保存数据的途径。除了 Core Data ,还有很多数据持久化的选择,包括 Realm , Couchbase Lite , Firebase 和 NSCoding 。

每一个都有自己的优点和缺点,包括 SQLite 自身。在没有数据持久层,作为开发者,基于你的应用要求来决定选择哪个选项。

SQLite 确实有一定的优势:

  • 在iOS的应用程序包没有增加额外的开销
  • 尝试和测试;第一个版本在2000年8月发布
  • 开源
  • 对于数据库开发人员和管理员熟悉的查询语言
  • 跨平台

SQLite 的优劣可以说非常直观和明显,所以这些我们会留下给你自己研究!

C的API

这部分的 SQLite 教程通过最常用和基本的 SQLite 的API来引导你。你会很快意识到用 Swift 的方法来包装C语言的API是个很好的想法,但是坐下来,我们先通过C语言去实现;你将在本教程的第二部分做一些 SQLite 的包装。

打开一个连接

在你做任何事情之前,你都需要先创建一个数据库的连接。

在开始部分的 playground 上添加如下方法:

func openDatabase() -> COpaquePointer {
var db: COpaquePointer = nil
if sqlite3_open(part1DbPath, &db) == SQLITE_OK {
print("Successfully opened connection to database at \ (part1DbPath)")
return db
} else {
print("Unable to open database. Verify that you created the directory described " + "in the Getting Started section.")
XCPlaygroundPage.currentPage.finishExecution()
}
}

上面的方法调用 sqlite3_open() 来打开或创建一个新的数据库文件,如果成功,将返回一个 COpaquePointer ;它是一个 Swift 类型,以为C指针不能直接在Swift中表示。当你调用这个方法,您将会捕获到返回的指针,用于与数据库交互。

许多的SQLite函数返回一个 Int32 结果,大多数这些代码被定义为在SQLite库常数,例如, SQLITE_OK 代表结果代码0。你可以在SQLite的网站上找到一个关于不同结果代码的列表。

去打开数据库,在你的 playground 上添加以下行:

let db = openDatabase()

按下 Play 按钮运行playground,观察控制台输出。如果控制台没有打开,按下左边的按钮来运行:

《SQLite 入门教程》

如果 openDatabase() 返回成功,你会看到以下输出内容:

Successfully opened connection to database at /Users/username/
Documents/Shared Playground Data/SQLiteTutorial/Part1.sqlite

username 是你的 Home 目录。

创建表

现在你已经连接上数据库文件了,你可以创建一张表。您将使用一个非常简单的表来存储联系人。

下面这张表由两个列组成, id 的的数据类型是 INT 是表的主键, Name 的数据类型是 CHAR(255) .

《SQLite 入门教程》 sqliteswift_table_diagram.png

添加下面的字符串,是创建表必要的SQL语句:

let createTableString = "CREATE TABLE Contact(" + "Id INT PRIMARY KEY NOT NULL," + "Name CHAR(255));"

下一步,添加此方法来执行创建表的SQL语句:

func createTable() {
// 1
var createTableStatement: COpaquePointer = nil
// 2
if sqlite3_prepare_v2(db, createTableString, -1, &createTableStatement, nil) == SQLITE_OK {
// 3
if sqlite3_step(createTableStatement) == SQLITE_DONE {
print("Contact table created.")
} else {
print("Contact table could not be created.")
}
} else {
print("CREATE TABLE statement could not be prepared.")
}
// 4
sqlite3_finalize(createTableStatement)
}

一步一步来分解:

  1. 首先,你创建一个指针便于第二步的引用。

  2. sqlite3_prepare_v2() 函数将 SQLite 语句编译成字节码并返回一个状态码,在执行任意数据库语句前这是很重要的一步。如果你对这个感兴趣,你可以在这里按查看更多,通过检查返回的状态码来确保编译成功。如果是这样的话,这个过程将移动到步骤3;否则,控制台会打印一条语句无法编译的消息。

  3. sqlite3_step() 运行已编译的语句,在这种情况下,只有当有一个结果时,才执行一次。之后在这个 SQLite 的教程它是必要的步骤,你会多次看到它的声明。

  4. 你必须总是调用 sqlite3_finalize() 编译语句删除它,避免资源泄漏。一旦一个语句已经完成,你就不应该再使用它了。

现在,你可以添加下面的方法在 playground 中调用:

createTable()

运行 playground ,你会在控制台上看下面的信息出现:

Contact table created

现在你的数据库里有一张表了,是时间往里面添加些数据了。添加一行数据, id1NameRay

插入一些数据

添加下面的SQL语句到你的 playground 的底部:

let insertStatementString = "INSERT INFO Contact (Id, Name) VALUES (?, ?);"

如果你没有太多开发SQL的经验也许看起来有一点奇怪。为什么值是问号呢?

还记得上面使用的 sqlite3_prepare_v2() 编译的句子?这个 ? 的语法是告诉编译器,当实际执行语句时,将提供真正的值。

这是有性能上的考虑,让你提前编译语句,这可能是一个性能增益,因为编译是一个昂贵的操作。编译后的语句可以重新使用不同的值。

接下来,创建下面的方法在你的 playground

func insert() {
var insertStatement: COpaquePointer = nil // 1
if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
let id: Int32 = 1
let name: NSString = "Ray" // 2
sqlite3_bind_int(insertStatement, 1, id)
// 3
sqlite3_bind_text(insertStatement, 2, name.UTF8String, -1, nil) // 4
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
} else {
print("INSERT staremnet could not be prepared.")
}
// 5
sqlite3_finalize(insertStatement)
}

下面介绍上面的方法是如何工作的:

  1. 首先,编写SQL语句并验证是否正确;
  2. ? 占位符得地方定义值。函数的名字 sqlite3_bind_int() – 意味着你绑定一个 int 值的声明。函数的第一个参数是绑定到的语句,而第二个参数是一个非零的索引用于绑定 ? 的位置。第三个和最后一个参数是值本身。这个绑定调用返回一个状态代码,但现在你假设它成功了的;
  3. 执行相同的绑定过程,但是这一次是一个文本值。在这个调用里有两个额外的参数;在这个SQLite的教程里你可以简单设为 -1nil 。如果你有兴趣,你可以在这里阅读更多关于绑定参数;
  4. 使用 sqlite3_step() 函数执行的语句和验证完成;
  5. 一如既往,最后确定声明。如果您要插入多个联系人,您可能会保留该语句,并使用不同的值重新使用它。

下一步,在 playground 中调用下面这个新添加的方法:

insert()

运行你的 playground 和验证您看到您在控制台输出:

Successfully inserted row.

挑战:多条插入

挑战时间!你的任务是更新 insert() 函数使它可以插入一组联系人。

作为一个提示,你需要重新编写 SQL 语句,用 sqlite3_reset() 返回到它的初始状态再执行一遍。

解决方案:插入多行

func insert() {
var insertStatement: COpauePointer = nil
// 1
let names: [NSString] = ["Ray", "Chirs", "Martha", "Danielle"] if sqlite3_prepare_v2(db, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
// 2
for (index, name) in names.enumerate() {
// 3
let id = Int32(index + 1)
sqlite3_bind_int(insertStatement, 1, id)
sqlite3_bind_text(insertStatement, 2, name.UTF8String, -1, nil)
if sqlite3_step(insertStatement) == SQLITE_DONE {
print("Successfully inserted row.")
} else {
print("Could not insert row.")
}
// 4
sqlite3_reset(insertStatement)
}
sqlite3_finalize(insertStatement)
} else {
print("INSERT statement could not be prepared.")
}
}

推荐阅读
  • IhaveaFirebasedatabasethatismodeledassuch:我有一个这样建模的Firebase数据库::users:some-random ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 设计完成后,将所完成的作品交由老师检查。管理进程接收申请进入的信号,在消息队列中取下申请进入队列的用户进程的信息,针对当前临界区状态,写一个回馈信息 ... [详细]
  • 三周内构建 JavaScript 全栈 web 应用
    从构思到部署应用程序的简单分步指南我在GraceHopperProgram为期三个月的编码训练营即将结束,实际上这篇文章的标题有些纰漏——现在我已经构建了三个全栈应用:从零开始的电 ... [详细]
  • google的GCM推送使用简介
    转载请注明出处:http:blog.csdn.netnewhope1106articledetails54709916GCM即GoogleCloudMessagin ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • CentOS 6.5安装VMware Tools及共享文件夹显示问题解决方法
    本文介绍了在CentOS 6.5上安装VMware Tools及解决共享文件夹显示问题的方法。包括清空CD/DVD使用的ISO镜像文件、创建挂载目录、改变光驱设备的读写权限等步骤。最后给出了拷贝解压VMware Tools的操作。 ... [详细]
  • 本文介绍了如何使用PHP代码将表格导出为UTF8格式的Excel文件。首先,需要连接到数据库并获取表格的列名。然后,设置文件名和文件指针,并将内容写入文件。最后,设置响应头部,将文件作为附件下载。 ... [详细]
  • C语言的经典程序有哪些
    本篇内容介绍了“C语言的经典程序有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何 ... [详细]
  • 初探PLC 的ST 语言转换成C++ 的方法
    自动控制软件绕不开ST(StructureText)语言。它是IEC61131-3标准中唯一的一个高级语言。目前,大多数PLC产品支持ST ... [详细]
  • 马拦过河卒pascal(题目,分析,样例输入输出,源程序,感受)马拦过河卒源程序名knight.???(pas,c,cpp)可执行文件名knight.exe输入文件名knight. ... [详细]
author-avatar
Still丶某某_546
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有