热门标签 | 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.")
}
}

推荐阅读
  • 本文探讨了Flutter和Angular这两个流行框架的主要区别,包括它们的设计理念、适用场景及技术实现。 ... [详细]
  • 2023年,Android开发前景如何?25岁还能转行吗?
    近期,关于Android开发行业的讨论在多个平台上热度不减,许多人担忧其未来发展。本文将探讨当前Android开发市场的现状、薪资水平及职业选择建议。 ... [详细]
  • Hibernate入门指南:单表数据库操作详解
    本文介绍了Hibernate作为全面的ORM框架的基础知识,并详细讲解了在MyEclipse环境中配置Hibernate以及进行基本的数据库单表操作的方法,包括增删改查等常见操作。 ... [详细]
  • ANSI最全介绍linux终端字体改变颜色等ANSI转义序列维基百科,自由的百科全书由于国内不能访问wiki而且国内关于ANSI的介绍都是简短的不能达到,不够完整所以转wiki到此 ... [详细]
  • iOS 面试实战:15 道经典面试题及解析
    本文精选了15道iOS面试题,并提供了详细的解答思路。旨在帮助开发者更好地准备面试,避免因准备不足而导致的紧张和焦虑。 ... [详细]
  • 远程访问用户 Kindle通过电子书实现控制
    介绍自2007年以来,亚马逊已售出数千万台Kindle,令人印象深刻。但这也意味着数以千万计的人可能会因为这些Kindle中的软件漏洞而被黑客入侵。他 ... [详细]
  • Python安全实践:Web安全与SQL注入防御
    本文旨在介绍Web安全的基础知识,特别是如何使用Python和相关工具来识别和防止SQL注入攻击。通过实际案例分析,帮助读者理解SQL注入的危害,并掌握有效的防御策略。 ... [详细]
  • 在现代移动应用开发中,尤其是iOS应用,处理来自服务器的JSON数据是一项基本技能。无论是使用Swift还是PHP,有效地解析和利用JSON数据对于提升用户体验至关重要。本文将探讨如何在Swift中优雅地处理JSON,以及PHP中处理JSON的一些技巧。 ... [详细]
  • 深入理解Java类加载机制及安全防护
    本文探讨了Java类加载的过程,包括加载、验证、准备、解析和初始化五个阶段,并详细解释了每个阶段的具体操作和意义。此外,文章还讨论了Java如何通过双亲委派模型来保障核心API的安全性,以及在特定情况下如何打破这一机制。 ... [详细]
  • PHP网站部署指南:从零开始搭建PHP网站
    本文提供了详细的步骤指导,帮助开发者在不同环境下成功部署PHP网站,包括在IIS和Apache服务器上的具体操作。 ... [详细]
  • 本文详细介绍如何在Spring Boot项目中集成和使用JPA,涵盖JPA的基本概念、Spring Data JPA的功能以及具体的操作步骤,帮助开发者快速掌握这一强大的持久化技术。 ... [详细]
  • 去控件化在线文档处理,推动高效信创办公环境
    探讨在线文档处理去控件化的趋势及其对构建高效信创办公生态的影响。 ... [详细]
  • 本文旨在探讨Swift中的Closure与Objective-C中的Block之间的区别与联系,通过定义、使用方式以及外部变量捕获等方面的比较,帮助开发者更好地理解这两种机制的特点及应用场景。 ... [详细]
  • SDWebImage第三方库学习
    1、基本使用方法异步下载并缓存-(void)sd_setImageWithURL:(nullableNSURL*)urlNS_REFINED_FOR_SWIFT;使用占位图片& ... [详细]
  • 本文介绍了EasyRTSPClient这一高效、稳定的RTSP客户端工具库,并详细阐述了其在与大华球机对接过程中遇到的预览问题及解决方法。 ... [详细]
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社区 版权所有