IOS-SQLite-学习指南-全-

IOS SQLite 学习指南(全)

原文:zh.annas-archive.org/md5/be0b888271ebd857b1f3abef24382bc6

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

SQLite 仍然是智能手机和平板电脑上移动应用程序广泛使用的数据库。对于有 SQL 经验的人来说,理解和学习它所能提供的内容以及它可以用作的应用程序将更容易。SQLite 于 2000 年发布,已发展成为移动设备开发的常用数据库。

D. Richard Hipp 先生在一家名为通用动力公司的公司期间,在一艘战舰上开发了它。最初用作存储,后来使用 B 树实现进行开发,这增强了它并使其能够存储行和事务。

本书为您提供了学习 SQLite(移动数据库)元素的机会,它与 MAC 操作系统、Xcode 以及 Apple 应用程序和 PhoneGap 的开发者 IDE 的交互;它使 HTML5 成为可能。它概述了与 SQLite 一起工作的简便性。

本书涵盖的内容

第一章, SQL 和 SQLite 简介,为您介绍了结构化查询语言(SQL)和移动数据库 SQLite 的背景。

第二章, 数据库设计概念,讨论了 SQLite 中的数据库概念。

第三章, 数据库管理,为您介绍了管理 SQLite 数据库的方法,并使您了解这个关系型数据库的不同组件。

第四章, SQL 基础,本章讨论了 SQL 的基础知识。它将概述 SQL 的主要可能性以及如何在 SQLite 上正确使用它。这是理解 SQL 的使用、其局限性和优势所必需的。

第五章, 公开 C API,处理 C API 及其扩展应用使用的方法,以及如何使用代码生成所需的应用程序。

第六章, 使用 Swift 与 iOS 和 SQLite,探讨了如何使用苹果公司的新编程语言 Swift 与 SQLite 一起使用。

第七章, 使用 PhoneGap 和 HTML5 进行 iOS 开发,探讨了如何使用 Xcode 与 PhoneGap 一起集成和编译源代码,包括 HTML5。

第八章, SQLite 的更多功能和进步,讨论了 SQLite 近年来如何变化,它如何发展到集成到各种现有技术中,以及其简单易用的公式如何确保它在其他人中的流行。

您需要这本书的内容

在这本书中,所需的软件如下:

  • Mac 操作系统:

    • OS X 10.9 或更高版本
  • 软件:

    • 支持 Swift 的 Xcode IDE 软件开发环境(版本 7.0-7.1.1+)

    • 来自PhoneGap.com的最新 PhoneGap 版本

    • 来自nodejs.org/en/的最新版 Node.js

本书面向对象

本书旨在帮助那些想要了解最强大、最灵活的移动数据库,用于以正确的方式在 Swift 或 Objective-C 中开发应用程序的人。如果你是 Objective-C 的专家程序员或对这个平台是新手,你将快速学习,掌握真实应用程序的代码,以有效地使用 Swift。

规范

在本书中,你会发现许多文本样式,用于区分不同类型的信息。以下是一些这些样式的示例及其含义的解释。

文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 昵称显示如下:“这种语言有多种语句,但大多数人会识别INSERTSELECTUPDATEDELETE语句。”

代码块设置如下:

SELECT parameter1, STTDEV(parameter2) 
FROM Table1 Group by parameter1 
HAVING parameter1 > MAX(parameter3)

任何命令行输入或输出都如下所示:

$ sqlite3 testdatabase.db

新术语重要单词以粗体显示。屏幕上看到的单词,例如在菜单或对话框中,在文本中如下所示:“然后在页面底部,在链接框架和库中点击+,将出现一个模态窗口。”

注意

警告或重要注意事项会出现在这样的框中。

提示

小技巧和技巧会像这样显示。

读者反馈

我们读者的反馈总是受欢迎的。告诉我们你对这本书的看法——你喜欢什么或不喜欢什么。读者反馈对我们很重要,因为它帮助我们开发出你真正能从中获得最大价值的标题。

要发送一般反馈,只需发送电子邮件至<feedback@packtpub.com>,并在邮件主题中提及书籍标题。

如果你在一个领域有专业知识,并且你对撰写或为书籍做出贡献感兴趣,请参阅我们的作者指南www.packtpub.com/authors

客户支持

现在你已经是 Packt 图书的骄傲所有者,我们有一些事情可以帮助你从购买中获得最大价值。

下载示例代码

你可以从你的账户中下载本书的示例代码文件。www.packtpub.com。如果你在其他地方购买了这本书,你可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给你。

你可以通过以下步骤下载代码文件:

  1. 使用你的电子邮件地址和密码登录或注册我们的网站。

  2. 将鼠标指针悬停在顶部的支持选项卡上。

  3. 点击代码下载与勘误表

  4. 搜索框中输入书籍名称。

  5. 选择你想要下载代码文件的书籍。

  6. 从下拉菜单中选择你购买这本书的地方。

  7. 点击代码下载

文件下载完成后,请确保使用最新版本的以下软件解压缩或提取文件夹:

  • WinRAR / 7-Zip for Windows

  • Zipeg / iZip / UnRarX for Mac

  • 7-Zip / PeaZip for Linux

下载本书的彩色图像

我们还为您提供了一个包含本书中使用的截图/图表彩色图像的 PDF 文件。这些彩色图像将帮助您更好地理解输出中的变化。您可以从www.packtpub.com/sites/default/files/downloads/Learning_SQLite_for_iOS_ColoredImages.pdf下载此文件。

勘误

尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果您在我们的书中发现错误——可能是文本或代码中的错误——如果您能向我们报告这一点,我们将不胜感激。通过这样做,您可以节省其他读者的挫败感,并帮助我们改进本书的后续版本。如果您发现任何勘误,请通过访问www.packtpub.com/submit-errata,选择您的书籍,点击勘误提交表单链接,并输入您的勘误详情来报告它们。一旦您的勘误得到验证,您的提交将被接受,勘误将被上传到我们的网站或添加到该标题的勘误部分下的现有勘误列表中。

要查看之前提交的勘误,请访问www.packtpub.com/books/content/support,并在搜索字段中输入书籍名称。所需信息将出现在勘误部分下。

盗版

在互联网上,版权材料的盗版是一个跨所有媒体的持续问题。在 Packt,我们非常重视保护我们的版权和许可证。如果您在互联网上发现任何形式的我们作品的非法副本,请立即提供位置地址或网站名称,以便我们可以寻求补救措施。

请通过发送链接到疑似盗版材料至<copyright@packtpub.com>与我们联系。

我们感谢您在保护我们的作者和我们为您提供有价值内容的能力方面的帮助。

问题

如果您在这本书的任何方面遇到问题,您可以通过发送电子邮件至<questions@packtpub.com>与我们联系,我们将尽力解决问题。

第一章。SQL 和 SQLite 简介

在本章中,我将向您介绍 结构化查询语言SQL)和移动数据库 SQLite。无论您是经验丰富的 SQL 技术人员还是新手,使用这本书将帮助您理解这个越来越受欢迎的酷炫主题。SQLite 是在移动智能手机或平板电脑上使用的数据库,它位于设备本地。SQLite 已被不同的供应商修改,以加固和确保其在各种用途和应用中的安全性。

SQLite 于 2000 年发布,现在已成为移动或智能手机上的事实上的数据库。它是一个占用空间小、开销低的开源软件,包含一个 RDBMS(关系数据库管理系统)。

D. Richard Hipp 先生 是 SQLite 的发明者和作者,SQLite 是在他加入美国海军的通用动力公司时在军舰上设计和开发的。编程是为 HP-UX 操作系统构建的,数据库引擎为 Informix。升级或安装数据库软件需要花费许多小时,对于这位经验丰富的 DBA数据库管理员)来说,这是一个超乎寻常的数据库。Hipp 先生希望有一个便携式、自包含、易于使用的数据库,它可以移动,快速安装,并且不依赖于操作系统。

最初,SQLite 1.0 使用 gdbm 作为其存储系统,但后来,它被自己的 B-tree 实现和数据库技术所取代。B-tree 实现得到了增强,以支持事务并按键顺序存储数据行。从 2001 年开始,为其他语言(如 Java、Python 和 Perl)编写的开源家族扩展被编写来支持它们的应用。数据库及其在开源社区和其他人中的受欢迎程度开始增长。

如维基百科所述,SQL 如下:

最初基于关系代数和元组关系演算,SQL 由数据定义和操作语言组成。SQL 的范围包括数据插入、查询、更新和删除、模式创建和修改以及数据访问控制。尽管 SQL 经常被描述为,并且在很大程度上是,一种声明性语言(4GL),但它也包括程序性元素。

国际化支持 UTF-16 和 UTF-8,并在 2004 年的版本 2 和 3 中包含了文本排序序列。它在 2004 年由 AOL美国在线)资助。它与各种浏览器一起工作,有时这些浏览器内置了对这项技术的支持。例如,有许多扩展使用 Chrome 或 Firefox,允许您管理数据库。

已向该产品添加了许多功能。随着手机的增长,这个快速简单的关系数据库系统将实现量子飞跃,其中数据库在移动和平板电脑应用空间的使用将增加。

SQLite 以 PostgreSQL 为参考点。SQLite 不强制进行类型检查。模式不会对其施加约束,因为值的类型是动态的,并且触发器将通过转换数据类型而被激活。

关于 SQL

1970 年 6 月,一份名为《大型共享数据银行的关系数据模型》的研究论文由E.F. Codd 博士发表。计算机协会ACM)接受了 Codd 的数据和技术模型,这已成为今天 RDBMS 的标准。IBM 公司发明了一种名为结构化英语查询语言SEQUEL)的语言,其中“English”一词被省略,成为SQL

SQL 已经成为 RDMS 的标准,被 Oracle、Sybase 和微软的 SQL Server 等数据库所使用。

今天,有美国国家标准协会ANSI)的 SQL 标准,并且有这种技术的许多变体。在提到的制造商中,开源世界也有其他可用的选项,例如,一个 SQL 查询引擎,如Presto

Presto 是开源下的 SQL 分发引擎,旨在执行交互式分析查询。Presto 查询可以在各种数据源大小的数据库下运行——从千兆到拍字节。

Facebook 和 Dropbox 等公司使用 Presto SQL 引擎进行数据仓库和相关应用程序的查询和分析。

SQL 是由在关系格式中使用元组和代数计算构建的数据操作和定义语言。这种语言有多种语句,但大多数人会认识到INSERTSELECTUPDATEDELETE语句。这些语句构成了数据库模式管理过程的一部分,并有助于数据和安全访问。SQL 在其设置中包括程序性元素。

SQLite 在当今行业中的地位如何?

公司可能会使用应用程序,但他们并不了解驱动他们数据存储和信息的 SQL 引擎。尽管在 1986 年已经成为 ANSI 的标准,但 SQL 的功能和特性在不同 SQL 系统之间并不是 100%可移植的。它们还需要代码更改才能变得有用。这些标准总是需要修订,以确保 ANSI 得到维护。

有许多工业和商业数据库,例如 Oracle、SQL Server 或 DB2,但它们没有一个像 SQLite 那样灵活、轻量或开源。尽管智能手机变得越来越强大,但你不能将它们的处理能力与现代桌面或笔记本电脑相提并论。SQLite,正如其名所示,是在轻量环境中运行的 SQL,它也是灵活和通用的。因此,目前最好的、轻量、功能齐全且可定制的移动数据库是 SQLite。

SQLite 不能与像 SQL Server、Oracle 和 MySQL 这样的企业数据库引擎相提并论。这些企业数据库系统提供了一个集中和受控的位置,而 SQLite 在移动设备上提供本地存储。SQLite 有效地基于规模经济和可靠性。它易于使用,体积小,健壮,并且不与这些企业数据库竞争。

由于无需人工输入或管理功能,SQLite 与“物联网”也很好地配合,因此对于处理无人机、医疗设备、机器人和传感器的应用,SQL 成为在多种移动应用上使用的理想候选者。

iOS 与 SQLite

在所有应用商店的数十万个应用中,很难找到一个不需要某种数据库来以特定方式存储或处理数据的应用。存在不同的数据格式和数据流,但它们都需要某种形式的临时或永久存储。少量数据可能不适用,但中等或大量数据将需要一种存储机制,如数据库来协助应用。

使用 SQLite 这样的数据库与 iOS 结合将使开发者能够使用他们现有的技能来运行他们的 DBMS。对于 SQLite,有一个嵌入式 C 库可供使用,并且可以通过Xcode IDE 与 iOS 结合使用。

苹果完全支持 SQLite,它使用包含语句作为库调用的一个部分,但开发者也可以使用FMDB,这是围绕 SQLite 的cocoa/objective-C包装器。

SQLite 的一些优点是它速度快、轻量级、可靠、使用现有的 SQL 知识、得到苹果在 Mac OS 和 iOS 上的支持以及许多开发者的支持,并且无需大量外部参与即可集成。

在页面的左侧突出显示主项目名称后,SQLite 3 库位于“常规”选项卡下。然后,在页面底部,在“链接框架和库”部分中,点击+按钮以出现一个模态窗口。输入单词sqlite并选择libsqlite3.dylib库,如图所示:

iOS 与 SQLite

实际上,是框架部分中的 C++包装器,称为libsqlite3.dylib库,允许 API 与 SQLite 命令一起工作。

在任何 SQL 处理开始之前,数据库应该已经打开并准备好查询,并且在数据检索成功后,应该将名为SQLITE_OK的常量设置为0

一旦使用了 C++包装器并且可以访问 SQLite 命令,使用 SQLite 与 iOS 结合的过程就会变得更容易。

小贴士

下载示例代码

您可以从www.packtpub.com的账户下载本书的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.packtpub.com/support并注册,以便将文件直接通过电子邮件发送给您。

您可以通过以下步骤下载代码文件:

  • 使用您的电子邮件地址和密码登录或注册我们的网站。

  • 将鼠标指针悬停在顶部的支持标签上。

  • 点击代码下载与勘误表

  • 搜索框中输入书籍的名称。

  • 选择您想要下载代码文件的书籍。

  • 从下拉菜单中选择您购买此书籍的来源。

  • 点击代码下载

下载文件后,请确保使用最新版本的软件解压缩或提取文件夹:

  • Windows 上的 WinRAR / 7-Zip

  • Mac 上的 Zipeg / iZip / UnRarX

  • Linux 上的 7-Zip / PeaZip

嵌入式数据库

SQLite 已被设计和开发,以便在其领域内与其他应用程序和进程协同工作。关系数据库管理系统(RDBMS)与需要存储信息但被隐藏、对用户不可见的本地应用程序软件紧密集成,这需要最少的行政管理或维护。

SQLite 可以与用户隐藏的不同 API 一起工作,并且需要最少的行政管理或维护区域。

RDMS SQLite 还将与其他应用程序兼容:

  • 它需要最少的监督。

  • 由于它是一个基于文件的系统,因此没有网络流量,访问速度更快。

  • 没有网络访问冲突或配置问题。

  • 没有权限或权限限制的访问限制。

  • 减少了大量的开销。

这些使得将您的应用程序部署到应用商店或其他位置更加容易和快捷。

图 1,在本节中展示,显示了不同组件如何以和谐的方式无缝协同工作,将数据与 SQLite 库和其他进程连接起来。这些展示了 Apache 和 C/C++进程如何与 SQLite-C 库协同工作,以便进行接口和链接,使其变得无缝并集成到操作系统中。

SQLite 已被开发和集成,以便它将与各种应用程序和多个解决方案进行接口和融合。作为一个轻量级的 RDBMS,它因其多功能性而能够独立存在,不会因为过于复杂而影响您的应用程序。它可以在许多平台上使用,并带有二进制兼容的格式,这使得它更容易与您的移动应用程序结合。

不同的 IT 专业人员将涉及 SQLite,因为它持有数据,影响性能,并涉及数据库设计、用户或移动界面设计专家、分析师和咨询类型。这些专业人员可以使用他们现有的 SQL 知识快速掌握 SQLite。SQLite 可以作为信息的数据处理器,或在内存中处理数据,以出色的表现运行。

图 1还概述了如何使用 SQLite 的 C API 接口与其他编程语言代码正确地接口不同软件组件的拼图。例如,C 或 C++代码可以编程以与 SQLITE C API 通信,然后与操作系统和数据库引擎通信。另一种语言,如 PHP,可以使用其自己的语言数据对象进行通信,这将反过来与 SQLite C API 和数据库通信。

SQLite 是一个很好的学习数据库,特别是对于想要使用能够打开他们视野以研究缓存、B-Tree 结构和算法、数据库设计架构以及其他概念的计算机科学家来说。

关于 SQLite 如何在移动设备上的其他应用程序中定位的更多信息,请参阅图 1

嵌入式数据库

图 1:SQLite 的 C API 接口

SQLite 数据库的架构

作为操作系统接口中的库,SQLite 将通过名为tclsqlite.c的程序实现许多功能。不同的语言中使用了不同的技术和保留字,但在这里我们使用了 C 语言。核心功能可以在main.clegacy.cvmbeapi.c中找到。还有一个用于 TCL 语言的 C 源代码文件,以避免任何混淆;SQLite 库的名称前缀使用sqlite3

标记器代码库位于tokenize.c文件中。其任务是查看传递给它的字符串,并将它们分割或分离成标记,然后传递给解析器。tokenize.c文件通过包含语句包含在代码中,并位于sqlite/src/tokenize.c目录区域。

解析器代码库位于parse.y文件中。SQLite 的解析器是Lemon LALR(1)解析生成器;它将标记的概念赋予它们意义。为了保持 RDBMS 的低内存占用,只使用一个 C 文件作为解析生成器。

然后,代码生成器用于从解析器输出的标记中创建 SQL 语句。它将生成一些虚拟机代码,这些代码将执行 SQL 语句的工作。如attach.cbuild.cdelete.cselect.cupdate.c等几个文件将处理 SQL 语句和语法。

虚拟机执行由代码生成器生成的代码。它具有内置的存储,其中每条指令可能有最多三个额外的操作数作为代码的一部分。源文件名为vdbe.c,它是 SQLite 数据库库的一部分。内置的还有一个专门创建以与数据库系统集成计算的引擎。

虚拟机有两个头文件。用于连接 SQLite 库之间的接口的头文件是 vdbe.hvdbeaux.c,它们包含其他模块使用的实用工具。vdbeapi.c 文件也通过 sqlite3_bind 和其他相关接口连接到虚拟机。C 语言例程从 SQL 函数中调用,以便将它们引用到头文件中。例如,count() 等函数定义在 func.c 中,日期函数位于 date.c 中。

B-tree 是 SQLite 中使用的一种表实现类型,其 C 源文件是 btree.cbtree.h 头文件定义了 B-tree 系统的接口。每个表和索引都有不同的 B-tree 设置,这些设置位于同一文件中。btree.c 中有一个头部分,其中包含 B-tree 的详细信息,这些信息位于一个大的注释字段中。

页面缓存页面缓存 使用 B-tree 将以固定大小的格式请求数据。默认大小为 1024 字节,但可以是 512 到 65536 字节。提交和回滚操作,以及数据的缓存、读取和写入,都由 页面缓存页面缓存器 处理。数据锁定机制也由 页面缓存 处理。名为 page.c 的 C 文件被实现来处理 SQLite 库内的请求,其头文件是 pager.h

操作系统接口 C 文件定义在 os.h 中。它说明了 SQLite 如何在不同的操作系统上使用,并且对用户来说是透明和可移植的,因此成为任何开发者的宝贵解决方案。还保留了一个抽象层来处理 Win32 和 POSIX 兼容的系统。不同的操作系统都有自己的 C 文件。例如,os_win.c 用于 Windows,os_unix.c 用于 Unix;两者都与其各自的 os_win.hos_unix.h 头文件相关联。

Util.c 是处理内存分配和字符串比较的 C 文件。Utf.c C 文件将包含 Unicode 转换子例程。

有关 SQLite 架构的更多信息,请参阅 图 2

SQLite 数据库架构

图 2:SQLite 架构图

Utf.c C 文件将包含 Unicode 数据,在 SQL 引擎中对数据进行排序,并使用引擎作为计算数据的一种机制。由于设备内存有限,数据库大小也有相同的限制,因此开发者必须跳出思维定式来使用这些技术。

这些类型的内存和资源管理在过去使用覆盖技术时形成了一部分方法,当时磁盘和内存有限:

    SELECT parameter1, STTDEV(parameter2)
      FROM Table1 Group by parameter1
      HAVING parameter1 > MAX(parameter3)

功能

作为其标准的一部分,SQLite 使用并实现了大多数 SQL-92 标准,但并非所有潜在的功能或功能部分都被使用或实现。例如,SQLite 使用并实现了大多数 SQL-92 标准,但并非所有潜在列。触发器的支持不是 100%,因为它无法将输出写入视图。

如前所述,对于列使用公共数据类型是不同的;大多数关系型数据库系统将它们分配给单个值。如果列的首选类型是整数,SQLite 会将字符串转换为整数。当绑定到这种脚本语言时,这是一个很好的功能,但这种技术不可移植到其他 RDBMS 系统中。与其他系统相比,它也因其没有良好的数据完整性机制而受到批评,尤其是在静态类型列方面。

在这两种数据处理方法之间有一些主要差异:一个是 Core Data,而 SQLite 方式类似于在用户界面和数据库本身之间有一个信息层。它确实有加快数据库交互读写过程和节省编写大量查询的优势。而 SQLite 是一个具有自身效率和限制的本地关系型数据库,可能不适合所有应用程序。有时,由于设备的速度,Core Data 可能直接具有 SQLite 的优势。

简而言之,你的应用程序将具有模型层对象,这些对象由一个框架持有和管理,即 Core Data。它管理 iOS 中对象的整个生命周期。这只是提供一些背景信息,以展示如何从数据库中读取数据以及这一过程的速度。

使用 SQLite 的优势

列出使用 SQLite 的几个优点:

  • SQLite 确实具有数据约束功能,并且可以在不将其加载到内存中的情况下编辑或删除表。

  • SQLite 在磁盘上存储数据,与 Core Data 相比,速度较慢。

  • 另一方面,Core Data 没有数据约束,可以使用应用程序的业务逻辑来实现。

  • 为了更新或删除表,必须将整个表加载到内存中。

  • Core Data 创建记录/行很快,但保存数据较慢。

  • Core Data 确实具有另一个优势,即它在内存中操作和工作,数据必须从磁盘加载到内存中。

  • Core Data 基于内存中的对象进行操作,或者可以使用标准的较慢的磁盘方法进行访问。

  • Core Data 适用于非事务性、单用户或单线程方法。SQLite 的功能是使用其文件数据库系统检索和存储数据。它通过在磁盘上存储数据,以增量或最小方式加载数据来操作。

  • 实际上,数据可以是事务性的、多用途的,并且线程安全。它将数据保存到磁盘上,并且对崩溃具有很高的容错性。如果你需要创建数十万行数据,它可能会变慢,但它确实有数据约束,例如唯一键。

  • SQLite 与许多语言绑定,如 Basic、C、C#、C++、Java、JavaScript、Lua、PHP、Objective-C、Python、Ruby 和 TCL。开源社区的使用和客户及开发者的使用使得其持续增长。

  • 这种轻量级的 RDMS 可以在 Google Chrome、Firefox、Safari、Opera 和 Android 浏览器上使用,并支持使用ADO.NET、ODBC、COM(ActiveX)和 XULRunner 的中间件。它还支持诸如 Django(基于 Python)、Ruby on Rails 和 Bugzilla(Mozilla)等 Web 应用程序框架。还有其他应用程序,如 Adobe Photoshop Light 和 Skype,使用 SQLite。它也是 Windows 8、Symbian OS、Android 和 OpenBSD 操作系统的组成部分。

  • 除了没有其他数据库引擎的大开销外,SQLite 还有一个主要增强功能,称为EXPLAIN关键字,具有显式类型。

  • 为了控制约束冲突,使用REPLACEON CONFLICT语句。

  • 在同一个查询中,可以使用DETACHATTACH语句访问多个独立的数据库。

  • 可以使用预定义的 API 创建新的 SQL 函数和排序序列,这提供了更多的灵活性。

  • 由于无需配置,SQLite 只需完成工作并运行。

  • 不需要列表,如REPLACEON CONFLICT过程。

  • 不需要初始化、停止、重启或启动服务器进程,也不需要管理员创建具有适当访问控制或安全许可的数据库。

  • 任何故障发生后,不需要用户操作来恢复数据库,因为它具有自我修复功能。

  • SQLite 比之前想象的更先进。与其他 RDMS 不同,它不需要通过服务器设置来提供数据或产生网络流量成本。没有 TCP/IP 调用,也没有频繁的前后通信。

  • SQLite 直接;操作系统进程处理对文件的数据库访问,并通过无中间人进程握手来控制数据库的读写操作。

  • 由于没有服务器后端,安装、配置或管理过程显著减少,并且数据库访问权限授予需要此类数据操作的程序。这在一方面是一个优势,但也是安全性和防止数据滥用、数据并发或数据行锁定机制的一个劣势。

  • 它还允许数据库同时被不同的应用程序多次访问。

  • 它支持跨平台数据库文件的一种可移植性形式,该文件可以通过数据库文件结构定位。数据库文件可以在一个系统上更新,并在具有不同架构的 32 位或 64 位系统上复制到另一个系统;这对 SQLite 没有影响。

  • 通过使用不同的架构和开发者的承诺,保持文件系统稳定并与以前、当前和未来的发展兼容,将允许这个数据库增长和繁荣。SQLite 数据库不需要将旧数据上传到新的、格式化和升级后的数据库;它只需工作即可。

  • 通过使用单个磁盘文件作为数据库,信息可以复制到 USB 上并共享,或者通过保持所有信息完整,在另一台设备上快速重用。

  • 这个便携式数据库 SQLite 的另一个特点是它的尺寸,可以从单个 512 字节页面开始,扩展到每页 65,536 字节、共 2,147,483,646 页,或者以字节计算为 140,737,488,224,256,相当于大约 140 太字节。大多数其他关系型数据库管理系统都更大,但 IBM 的 Cloudscape 较小,有 2 MB 的 jar 文件,但仍然比 SQLite 大。

  • 火鸟替代方案的客户端(前端)库大约为 350 KB,而伯克利 Oracle 数据库则大约为 450 KB,不包括 SQL 支持,并且有一个简单的键/值对选项。

  • 这个高级便携式数据库系统及其源代码属于公共领域。然而,对于一些测试代码和文档,存在开源许可问题和控制。

  • 这对那些可能想要编写新扩展或与他们的程序一起工作的数据库功能(可能成为 SQLite 的“产品扩展”)的开发者来说是个好消息。

  • 由于一切都有专利、有限访问或根本没有访问权限,您无法获得此类对 SQL 源代码的访问。

  • 有开发者签署的声明,放弃对 SQLite 代码的任何版权利益。SQLite 之所以不同,是因为它根本不受版权法的管辖或统治,版权法监控软件应该如何真正工作或被使用。

使用小分配和可变长度记录,应用程序运行更快,数据库访问更快,使用显式类型,数据库小而敏捷。

使用这种关系型数据库管理系统(RDBMS)的简便性使得大多数中级程序员更容易使用这项技术创建应用程序,因为它有详细的文档和示例。

其他关系型数据库管理系统在内部比较复杂,与数据结构和对象有链接。SQLite 包含一种虚拟机语言,它在查询前使用保留词EXPLAIN

虚拟机通过提供一个优秀的过程或受控环境,在后台(结果计算和输出)和前端(SQL 被解析和执行)之间增加了对这个数据库引擎的好处。

SQL 实现语言与其他关系型数据库管理系统相当,特别是与其轻量级基础相比,它支持递归触发器并要求FOR/EACH ROW行为。FOR EACH语句目前不支持,但未来不能排除其功能。

如本章所述,SQLite 是一个敏捷且易于使用的数据库,开发者可以快速参与其中,使用现有技能,并将系统输出到移动设备和平板电脑上,比以往任何时候都容易。借助 HTML5 和其他 JavaScript 框架的帮助,SQL 的进步和 SQLite 安装数量将实现量子飞跃。

与 SQLite 一起工作

SQLite 的网站可在www.sqlite.org找到,您可以在那里下载数据库、文档和源代码的二进制文件,这些文件适用于 Linux、Windows 和 MAC OS X 等操作系统。

SQLite 的共享库DLL是用于 Windows 操作系统的库,可以通过 Visual Studio 使用 C++语言安装或查看。因此,开发者可以使用通过应用程序链接的当前库编写代码。当执行发生时,DLL 将加载,代码中的所有引用将在正确的时间链接到 DLL 中的相应部分。

SQLite3 命令行程序CLP—是一个自包含的程序,它包含所有在命令行上运行的组件。

它还附带了一个 TCL 扩展。因此,在 TCL 中,你可以连接和更新 SQLite 数据库。SQLite 下载包含适用于 Unix 系统的 TAR 版本和适用于 Windows 系统的 ZIP 版本。

iOS 中使用 SQLite 的示例

以下是一个简单的示例,展示了如何使用 Xcode 在 iOS 中与 SQLite 数据库一起使用。它概述了创建应用程序和数据库以及选择数据的基本步骤。

要开始,让我们启动 Xcode,并使用单视图应用程序选项创建一个模板,如图所示:

使用 SQLite 与 iOS 的示例

点击下一步按钮,进入此过程的下一屏幕。在产品名称字段中,输入SimpleCalculator作为语言,并选择Swift。对于设备字段,选择iPhone。然后,点击下一步按钮,进入下一屏幕,如图所示:

使用 SQLite 与 iOS 的示例

在以下截图中,选择代码将驻留的目录。现在,我们可以查看 Xcode 开发者工具创建的内容。然后,选择一个设备来显示信息;在我们的例子中,使用 iPhone 6s。

查看源代码目录,如图所示:

使用 SQLite 与 iOS 的示例

以下是一张截图,显示了在 Xcode 中打开的SimpleCalculator应用程序。选择iPhone 6s作为开发设备:

使用 SQLite 与 iOS 的示例

接下来,点击播放按钮,它将编译和构建应用程序,如图所示,并将出现一个空白屏幕:

使用 SQLite 与 iOS 的示例

上一张截图显示了要构建的应用程序,下一张截图显示了编译和运行图像后的空白屏幕。

这种方法让你通过 Swift 作为画布,掌握 iOS 应用程序的基础。

在这个简短的示例中,我们将使用SQLiteDB.swiftString-Extras.swift来处理 SQLite 数据库,包括Bridging-Header.h文件。在构建设置选项中,查看Objective-C 桥接头,双击它,并将其桥接到Bridging-Header.h,你也可以将其拖动以显示它已被链接。

如前所述,通过导航到通用 | 链接框架和库,将libsqlite3.0.dylib添加到链接框架中;然后,添加Libsqlite3.0.dylib

现在,重新构建项目以显示它正在工作:

使用 SQLite 与 iOS 的示例

点击模拟器按钮,然后点击退出以停止当前编译的模拟器程序。程序将无问题编译。接下来,必须创建一个数据库实例,如下面的代码所示。使用SQLite.DB.query方法执行这些命令:

  • 首先需要一个实例:

    let testdb = SQLiteDB.sharedInstance()
    
  • 要运行此查询,使用以下代码与SQLiteDB.query方式相结合:

    var theresult = testdb.query("select * from people where county = 'Berks'", parameters: nil)
    for row in result
    {
        println(row["name"]!.asString())
    }
    
  • 例如,要删除一条记录,请按照以下代码片段操作:

    testdb.execute("delete from people where county = 'Bucks' ", parameters: nil)
    

摘要

在本章中,你将了解 SQL 的历史、关系数据库的影响以及移动 SQL 数据库的使用,即 SQLite。本章概述了 SQLite 的历史和起源以及它是如何发展成为迄今为止在移动设备上使用最多的数据库。在下一章中,你将学习数据库概念组件以及如何设计 SQLite 数据库。下一章将展示 SQLite 数据库设计的基本要素。

第二章:数据库设计概念

在本章中,你将学习 SQLite 的数据库概念。就像大多数数据库一样,SQLite 也可以使用名为INSERT的 SQL 命令来添加数据。它还可以使用UPDATE命令修改数据,使用DELETE命令删除数据。它还可以使用SELECT命令检索数据。

这四个命令构成了市场上任何 SQL 数据库 RDMBS 的基础。这组命令操作数据,这种类型的搜索称为查询

数据库基础知识

这种持久和结构化的数据存储方式简单地称为数据库,数据本身是使用表格存储的。每个表格由列和行组成,其外观和感觉类似于Microsoft Excel

SQLite 基于 C 语言和市场上的相关 API(RDBMS)。例如,C 语言易于理解,并且基于 RDBMS 的数据库设计基础。然而,学习实际的 API 将有助于提升你的技能和理解。

为了理解 API,你必须学习构成数据库的组件,以提升你的知识。理解数据结构、SQL 事务、并发性和数据锁定机制,以及创建优化的查询将有助于你设计出色的数据库系统。

最后,你需要将这种理解应用到你所编写的应用程序的软件代码中,看看它是如何集成和执行的。本章将进一步讨论 API 语言扩展。

SQLite 的设计目标是使管理和操作简单易用,易于管理。SQLite 是ACID原子性一致性隔离性持久性)兼容的,并且完全使用T-SQL进行事务处理。

作为设计的一部分,SQLite 数据库具有多种数据类型,就像大多数数据库一样。其中一种类型是INTEGER类型,它具有 64 位数值。这个数据库使用 64 位数值,数据存储在 1、2、3、4、5、6 或 8 字节中。TEXT类型编码使用 UTF-8 在数据库中存储。BLOB数据类型可以直接存储,默认大小为 1,000,000,000 字节。

注意

SQLite 还使用REAL类型,它是一个 64 位浮点值,同时也有标准的NULL值。REAL类型将应用于FLOATDOUBLEREAL数据类型。TEXT类型适用于NCHARNVARCHARTEXTVARCHAR数据类型。NUMERIC类型适用于DATEDATETIMEBOOLEAN。SQLite 还使用CRUD创建读取更新删除),并且这个数据库不区分大小写

语句如下所示:

  • CREATE语句用于在 SQLite 数据库中创建新表。这里显示了CREATE TABLE的基本语法和简单示例。CREATE TABLE语句有一个固定的数据库名。它后面跟着一个表名,用括号括起来。在这个语句中,有一个要创建的列(s)的列表,从它们的名称和数据类型开始,如下所示:

    • CREATE table database-name. table-name( column1 datatype, column2 datatype, column3, datatype, PRIMARY KEY column1);
  • INSERT语句将在前半部分有一组列,后面跟着一个表名。后半部分将有变量,其中来自这些变量的数据将被插入到表中。确保程序员使用与创建的列相同的数据类型很重要;否则,将出现错误或警告:

    • INSERT into table-name(column1,column2,column3) VALUES(variable1,variable2,variable3);
  • UPDATE语句用于更新表中的记录或行。UPDATE语句将有一个表名,后面跟着左侧要更新的列的集合和一些数据变量,如下所示:

    • UPDATE table-name SET column1=variable1, column2=variable2, column3=variable3) [where variable4 = 10];
  • SELECT语句用于从表中选择信息、记录或行。这如图 7 所示。SELECT语句将在前半部分有一组列,后面跟着一个表名和一个条件,如下所示:

    • SELECT column1, column2, column3 FROM table-name WHERE column1 > 10;
  • DELETE语句用于从表中删除记录或行。这在此处显示。DELETE语句将在前半部分有一组列,后面跟着一个表和任何条件:

    • DELETE from table-name where column1 >10;

扩展和核心 API 是构成用 C 语言制作的 API 的部分。核心数据库执行处理 SQL 语法和连接到数据库等功能。其他任务,如错误捕获和字符串格式化,也由核心 API 处理。如前所述,扩展 API 允许程序员通过添加或扩展当前 API 的新功能来添加目前不存在或作为 SQLite 程序当前定义的功能。

虽然数据结构已经概述,如前所述,使用标记化器或解析器,它们的重要性降低,因为编码者对其他部分更感兴趣,如连接语法、参数或当前函数,而不是产品的内部。为了编写一些好的代码,程序员必须了解 SQLite 锁、事务和 API 本身。

虽然不是 API 本身的一部分,但 SQLite 系统的分页器B 树部分在锁定和事务机制中作为重要部分做出了贡献。

有八种方法和两种对象构成了 SQLite 数据库系统的 C/C++接口部分。这两个对象是:sqlite3,这是实际的数据库连接对象,以及sqlite3_stmt,这是prepare语句对象。

八种方法包括以下内容:

  • sqlite3_exec(): 这是一个包装函数

  • sqlite3_close(): 这是sqlite3的析构函数

  • sqlite3_finalize(): 这是sqlite3_stmt的析构函数

  • sqlite3_column(): 这个接口保存sqlite3_stmt的列值

  • sqlite3_step(): 这允许你移动到下一个结果行,是sqlite3_stmt的改进。

  • sqlite3_bind(): 这是将 SQL 从存储的应用程序数据中分解成参数的方式

  • sqlite3_prepare(): 这是sqlite3_stmt构造函数的一部分,其中从编译后的 SQL 生成字节码,以便执行 SQL 语句(SELECTUPDATE

  • sqlite3_open(): 这是sqlite3的构造函数,它允许连接到现有的或新的 SQLite 数据库

最初,SQLite 易于学习,只有五个 C/C++接口,但现在,它已经增长到超过 200 个 API 的大小、功能和接口。使用 200 个 API 可能会让人感到畏惧,但 SQLite 的设计方式使得你只需使用 API,但现在,它已经增长到更大的规模和功能。

这六个核心接口一旦掌握,将使程序员对 SQLite 有更深入的理解。它们在此列出:

  • SQLite3_open(): 这个函数建立与 SQLite 数据库的连接,一旦成功,将返回一个数据库连接对象。其他接口在SQLite3_open()接口设置之前将不可用。它们需要一个起点,或对数据库的引用,以及一个数据库连接对象。

  • SQLite3_prepare(): 这个函数将 SQL 语句转换并设置成格式化的对象,输出将是一个指针,该指针将存储对该对象的引用。为了继续前进,这个接口需要一个由SQLite3_open()函数产生的数据库连接对象。

  • SQLite3_column(): 这个接口不查询 SQL,它只是生成一个预编译语句。这个接口现在不再是新应用的优先选择,但必须使用替代的SQLite3_prepare_V2()接口。

  • SQLite3_step(): 这个接口将查看由 SQLite3_prepare() 函数设置的预处理语句,并从当前记录集中返回一个单列。这不仅仅是一个函数,而是用于返回不同数据类型值的函数类型的占位符。这些构成了结果集的一部分。还有其他一些是 sqlite3_column() 设置的一部分,它们是:sqlite3_column_blob()sqlite3_column_bytes()sqlite3_column_bytes16()sqlite3_column_count()sqlite3_column_double()sqlite3_column_int()sqlite3_column_int64()sqlite3_column_text()sqlite3_column_type()sqlite3_column_value()

  • SQLite3_finalize(): 这个函数是销毁预处理语句的接口,以防止系统中的内存泄漏。

  • SQLite3_close(): 这个接口将在关闭或停止操作之前关闭任何数据库连接和预处理语句。

还有其他一些例程,如 sqlite3_bind()sqlite3_reset(),允许重复使用先前语句。通常,语句只创建、准备和销毁一次,但上述例程可以在多个实例中使用。

SQLite 有一个 sqlite3_config() 接口,在发起任何数据库连接之前首先被选择。这个接口将能够设置数据库的全局更改。它还可以分配内存,为实时嵌入式系统设置分配器,并为预定义的应用程序使用设置页面缓存。它还可以对不同线程模型进行调整。

这个数据库系统是灵活的,使用 sqlite3_create_collation()sqlite3_create_function()sqlite3_create_module()sqlite3_vfs_register() 函数将允许 SQLite 系统在 RDBMS 上拥有新的专有功能。例如,sql_create_function() 函数将为聚合或标量目的创建额外的功能。这些是 sqlite3_aggregate_context()sqlite3_result()sqlite3_user_data()sqlite3_value()

这些是 SQLite 系统的标准内置功能,证明了该系统对程序员来说是多么灵活。正是这种灵活性,加上帮助它成长和发展的技术,使得它成为了今天最好的移动 SQL 数据库。

此外,还有许多其他接口和函数,太多以至于无法包含在这本书中。它们可以在该产品的 C/C++ 接口规范下找到。

默认情况下,SQLite 将完成程序员、用户或 DBA 所需的大部分任务。程序员总是寻求超越关系型数据库系统的正常界限,或者利用这些扩展来满足他们的解决方案需求。

使用 SQLite 的原因

SQLite 拥有许多使其成为移动技术优秀数据库的特点。例如,无需管理或配置,事务是原子的,数据库包含在一个单一的跨平台文件中,并且具有高级功能,如表表达式和部分索引。使用 SQLite 的原因在此列出:

它有一个小型、多功能且易于使用的 API。它非常符合标准,并使用符合 ANSI-C 的代码编写。没有对外部程序或服务的依赖,代码注释良好。源代码属于公共领域,并提供了独立的CLI命令行界面)。它是跨平台兼容的,与 Mac、Linux、BSD、Android、Solaris、VxWorks 和 Windows(WinCE、Win32、WinRT)兼容。

它的代码占用空间非常小,配置时小于 500 kB。使用此数据库的应用程序范围非常广泛。几乎所有的产品都可以拥有或需要 SQLite 可以处理的数据库。

它可能没有企业系统所有的功能,但它非常灵活且易于获取。Adobe、Dropbox、Skype 等许多公司都使用 SQLite。

SQLite 使用自己的测试设施和标准独立进行测试。有针对内存使用、崩溃和断电、模糊测试边界值和禁用优化测试、回归测试和行为检查等的测试。测试工具也是独立开发和验证的。

SQLite 的测试过程经过充分测试和成熟,TCL 测试使用 TCL 脚本语言构建。测试工具使用创建 TCL 界面的 C 代码制作。有超过 800 个测试脚本文件,包含超过 10 GB 的数据和超过 30,000 个测试用例。

还有针对 SQL 逻辑的测试,这些测试将 SQL 语句针对其他数据库引擎运行,例如 SQL Server、PostgreSQL、Oracle 和 SQLite 本身。这些构成了 SLT(SQL 逻辑测试)的一部分,该测试运行超过 700 万个查询和 1GB 的测试数据,作为测试负载的一部分。

此外,还有许多类型的压力和性能测试,包括异常测试,这些测试包括对 SQLite 在各种检查中的行为进行测试,并查看错误发生时的表现。所有测试都在 SQLite 支持的所有平台上运行。存在一个测试脚本的子集,用作快速测试;然而,仍有超过 200,000 个测试用例——足以捕获任何错误或不适配的代码——可以快速执行。

也有用于检查内存使用的测试,这些测试会查看内存分配和malloc()函数的使用情况。所有 SQL 数据库都使用malloc()函数来分配和释放内存。由于 SQLite 在嵌入式系统中被大量使用,因此需要优雅地处理错误。

进行 I/O 测试以确保正确处理和解决 I/O 错误。这些问题可能与网络错误、配置、磁盘问题或权限有关。创建错误以观察其影响以及软件如何处理它们。

使用虚拟文件系统(VFS)来模拟数据库崩溃也是测试程序的一部分。还有使用电力故障的模拟,以便记录任何测量数据。崩溃测试过程是单独完成的。

此外,还有一些模糊测试,以确保 SQLite 能够处理奇数和不同的输入,并且所有结果都经过检查。会启动进程并使用 VFS 来模拟崩溃。除了标准的模糊测试外,还有针对 SQL 的模糊测试,检查数据库的语法和输入,以检查响应和结果。这些构成了 TCL 测试的一部分,并且有超过 10 万个模糊测试。所有结果都被记录和分析。

所有针对此数据库的分支测试都已达到 100%的测试和测量。同时,也有测量和测试来确保任何自动资源泄漏都能被检测、记录并处理。通常,资源泄漏发生在特定情况下,资源由malloc()函数分配,但在其他进程可能需要相同资源或某种形式的共享资源时,资源没有被释放。当资源没有按照指示释放或释放时,就会导致资源泄漏。

SQLite 还具有动态分析功能,在代码执行或在线使用时检查内部和外部 SQLite 代码。这种分析类型用于确保 SQLite 为用户提供最佳的可用性和质量。

Valgrind是 Linux 二进制和 x86 环境的模拟器。作为一个模拟器,它运行得较慢,但非常有效。Memsys2有一个可插拔的内存分配系统;它使用malloc()free()函数。如果 SQLite 使用SQLite_MEMDEBUG编译时选项编译,那么作为调试内存分配器的一部分,malloc()realloc()free()函数周围将使用更大的包装器。如果使用 Memsys2,它将在运行时查找内存分配错误。

SQLite 中有mutex子系统,使用sqlite3_mutex_held()sqlite3_mutex_notheld()函数。这是一个可插拔的子系统,这两个接口检测特定线程是否存在于mutex子系统中。SQLite 使用assert()函数集来确保多线程应用程序在数据库系统中正确工作。

SQLite 使用回滚日志来确保在实际上对数据库进行更改之前记录数据库上的所有更改。SQLite 必须与不同的条件一起工作,以避免冲突或引起必须管理的未确定或异常行为。由于代码是用 C 语言开发的,它可能在开发期间与许多实现和库一起工作,但在生产区域,它必须确认并且有时可能不起作用。

因此,可能会尝试使用负数进行移位等检查,或者尝试使用memcpy()函数复制重叠的缓冲区,并检查无符号或带符号变量是否适用于char数据类型。为了应对这些问题,编译器(GCC)可能使用-fraction选项在测试套件中。

在代码发布之前,它将进行 ping 操作并检查无符号或带符号、分析或编译时错误,然后再继续。以下两个连接——连接 1连接 2——如下所示:

使用 SQLite 的原因

图 9:带有 C API 的 SQLite 对象模型

图 9概述了程序员将查看的视图——B 树和分页器,而不是标记化器或解析器等组件。图 9概述了组件之间的关系。为了正确理解 SQLite,程序员必须了解 SQLite 的锁、API 和事务。

图 9所示,分页器和 B 树访问在锁和事务中是禁止的,但很重要。当 API 有许多数据结构时,与数据库的连接和 SQL 语句是最重要的。例如,任何 SQLite 数据库的连接都保持为一个事务,并且也是一个连接到 RDBMS 的连接。SQL 语句在内部以虚拟数据库引擎VDBE)字节码的形式表示。

与 SQLite 的 B 树和分页器组件一起,它将支持每个连接中的许多数据库对象,如图 9 所示。每个数据库对象都有一个 B 树对象,它与分页器对象有关联。每个连接中的 SQL 代码(SQL 语句)如图 9 所示。每个数据库对象都有一个 B 树对象,它与分页器对象有关联。

当 B 树需要信息时,它会提示分页组件从数据库中获取数据。分页组件将数据移动到其内存缓冲区,然后 B 树组件通过其游标将其关联起来以检索和查看数据。

执行 SQL 语句和命令是 API 的主要部分,有两个方法,即准备或包装查询。如果游标修改了页面,则必须保留原始页面/数据,以防数据库回滚。分页器非常重要,必须处理来自 RDBMS 的读写事件。

一旦执行了操作,就会设置一个事务。例如,数据库连接设置将被视为一个事务。还请记住,在任何给定时间,连接不能打开或可用多个事务。

因此,来自标准连接的 SQL 语句将在同一事务中工作。如果你的程序需要在不同事务中执行多个语句,你必须使用多个连接,如图 9 所示。

了解如何从应用程序设置到 SQLite 数据库的数据库连接非常重要。如果没有连接,那么用于检索、更新或插入数据的任何命令都是无用的。连接语句将定义数据处理及其名称,并设置事务以允许数据传递到数据库并返回。一旦建立连接,其余的过程将设置数据库的交互性。虽然完成这个任务并不困难,但设置数据库是学习的重要部分,因为它是所有数据库活动和应用程序的起点。

数据库连接

sqlite3_open() C API 函数用于打开到数据库的连接,并且该连接被保存在单个操作系统文件中。此函数实际上打开文件,因此,建立了一个安全且不共享的连接。如果使用内存选项,那么数据库将在随机存取存储器RAM)中创建,一旦建立连接。当关闭连接时,数据库将从 RAM 中删除。

SQLite 将尝试打开现有数据库,如果输入的数据库名称不存在,则它将假定程序员想要创建一个。如果你想要创建数据库然后关闭它而不进行任何操作,例如创建表,SQLite 非常聪明:它实际上不会花费资源创建数据库,而只是一个空文件将存在:

sqlite3 aFile.db "create table aTable(field1 int); drop table aTable;"

前面的语句将创建所需的默认文件,其中包含一个表,然后将其删除/删除,留下一个没有任何表的干净数据库。这可能是最整洁的方式来展示一个空数据库。

当打开 SQLite 数据库时,程序员或数据库管理员可以指定页面大小,范围从 512 字节到 32,768 字节。默认情况下,SQLite 将使用 1,024 字节的页面大小。为了获得更好的性能,开发者可以考虑将 SQLite 数据库的页面大小设置为操作系统页面大小,这将使操作更加高效。

这一切都取决于你将要设计的应用程序类型;注意列的类型、大小和类型等细节,这将使表和数据库设计更加高效并表现良好。例如,如果你处理的应用程序有大量的二进制数据,数据库页面大小将增加以匹配数据的加载或选择。page_size 参数用作每个数据库页面大小的组成部分。

准备查询

这些是构成 SQLite 接口的八个方法和两个对象。这些是每个用户/读者在使用 SQLite 编码时必须了解的基本函数列表。这些语句不会改变,其功能也不会改变。这些是确保用户了解名称、格式以及这些函数使用位置的关键语句:

  • sqlite3: 数据库连接对象,由 sqlite3_open() 创建,由 sqlite3_close() 销毁

  • sqlite3_stmt: 准备语句对象,由 sqlite3_prepare() 创建,由 sqlite3_finalize() 销毁

  • sqlite3_open(): 打开数据库(新或现有)并使用构造函数 sqlite3

  • sqlite3_prepare(): 将一些 SQL 文本编译成字节码以执行更新或查询任务,并且是 sqlite3_stmt 的构造函数

  • sqlite3_bind(): 将应用程序数据存储到原始 SQL 的参数中

  • sqlite3_step(): 将 sqlite3_stmt 进一步推进到下一行或完成

  • sqlite3_column(): 当前行结果概述 sqlite3_stmt 的列值

  • sqlite3_finalize(): sqlite3_stmt 析构函数

  • sqlite3_close(): sqlite3 析构函数

  • sqlite3_exec(): 一个包装函数,用于使用 sqlite3_prepare()sqlite3_step()sqlite3_finalize()sqlite3_column() 对一个或多个 SQL 语句进行操作

sqlite3_prepare_v2() 函数用于准备和执行 SQL 语句。准备函数是 SQLite 作为以下三个阶段过程的一部分使用的方法:

  1. 首先是准备阶段,然后是执行阶段,最后是最终化阶段。在准备阶段(第一步),正如在第一章中所述,SQL 和 SQLite 简介,组件概述了解析器、标记器和代码生成器,以调查 SQL 并使用 sqlite3_prepare_v2() 函数与编译器一起生成语句。然后,使用 sqlite3_stmt 函数创建一个字节码处理句柄,该句柄整理并使用相关资源以执行语句。

  2. 其次,SQLite 中的 VDBE 将字节码执行,使用 C API。SQLite3_step()将与(VDBE)一起工作,遍历字节码,根据需要查看锁定资源。不同的语句在 VDBE 中工作方式不同,但以SELECT语句为例,作为结果集的一部分使用sqlite3_step()SQLITE_ROW()将被设置,并且过程将遍历整个数据集,直到达到SQLITE_DONE。集合中的其他语句,包括UPDATEINSERTDELETE,将在 VDBE 中直接执行。

  3. 第三步是最后一步,关闭 VDBE 的资源;sqlite3_finalize()函数执行此操作。一旦sqlite3_finalize()函数执行并且资源可用,程序将通过 VDBE 结束,并且语句句柄也将关闭。

参数化 SQL

在 C 代码和 API 中使用 SQL 将涉及参数化 SQL——在 SQL 语句中包含数据占位符的方式。这些是两种参数化绑定类型:命名和位置。请参阅图 10 以了解更多关于这些类型参数化绑定如何使用的详细信息。第一个语句是位置性的,其位置由问号定位或标记,这些位置基于列的数量。

在可编程语言(如 C 或 Java)中设置的真正变量名,如图 10 中的第二个插入语句所示,概述了使用冒号作为前缀在 SQL 语句中指示的命名参数。如果没有要绑定的值,默认使用NULL作为默认值。

一旦一个语句被绑定,你可以多次调用它而不会浪费重新编译的性能或时间。

使用参数化 SQL 的整个想法是使用不同的参数重用相同的代码而不需要重新编译。它节省了资源和时间,并提高了效率。如果设计允许,这允许现有代码被多次重用,以节省更多代码并提高效率。例如,如果你使用引号或字符表示复数,SQLite 默认将转义字符并插入正确数据并正确转换。

它还阻止 SQL 注入、SQL 渗透以及简单的语法问题或错误。对于公司来说,SQL 注入是一个安全漏洞,允许黑客欺骗系统在未授权的地方添加或修改数据。在浏览器中,当看到网站的地址时,数据输入有时没有任何加密,或者在前后端没有进行数据检查,以允许渗透。如图 12 所示和解释的 SQL 注入表明,依赖于使用%s字符串的输入的开放代码可以被视为开放的,并且可能影响数据库中的数据:

参数化 SQL

图 10:使用参数化 SQL

以下代码片段显示了如何使用一组参数编译一个语句;使用function _reset()方法将允许相同的编译 SQL 代码再次使用不同的参数:

#  example of using reset  - START
db1= open('property.db')
sql_statement= db1.prepare('insert into property_info(id,property_id,desc) values(:id,:pr_id,:desc)')
sql_statement.bind('id','100')
sql_statement.bind('property_id','1')
sql_statement.bind('desc','this is a test')
sql_statement.step()
# Reuse existing compiled parameters
sql_statement.reset()
sql_statement.bind('id','200')
sql_statement.bind('property_id','2')
sql_statement.bind('desc','this is a test again')
# End
statement_sql.finalize()
db1.close()

错误处理

在编写系统时处理错误是强制性的,尤其是如果是为了移动设备;因此,注意细节和通过代码捕捉问题至关重要。程序员使用SQLITE_BUSYSQLITE_ERROR函数来通知和捕捉错误,并将它们存储起来以供后续分析。

例如,当资源如锁无法授予或不可用时,SQL_ERROR会被激活,而SQL_BUSY则涵盖事务和相关问题。另一个名为sqlite3_errcode()的函数将处理任何通用的 SQLite 错误。这些方法和函数是处理 SQLite 错误的标准方式。

db.exec 语句中的查询

sqlite3_get_table()函数用于执行实际返回数据的 SQL 语句,例如SELECT语句,而sqlite3_exec()函数是单向流量执行,不返回任何数据,例如INSERT语句。以下代码提供了更多信息:

db1= open('property.db')
sql_statement= db1.exec("insert into property_info(id,property_id,desc) values(1,2,'Property Description 1')")sql_statement= db1.exec("insert into property_info(id,property_id,desc) values(2,2,'Property Description 2')")

SQL 注入攻击

SQLite 和 SQL 语句通常还存在另一个问题:SQL 注入攻击。这些攻击可能导致网站被篡改,数据损坏,并影响您网站及其客户的声誉。如果 SQL 参数的输入是直接的,那么可能存在可被利用的弱点。SQL 数据输入必须进行检查和过滤,以确保没有人能够使用数据元素更改当前语句,甚至替换 SQL 语句以执行恶意行为。这可以通过以下语句实现:

SELECT * from property where property_name='%s';

以下代码显示了注入可能发生的地方,其中%s是输入字符串,它可以被更改成其他内容,从而改变结果。为了保护 SQL,限制输入,使用存储过程参数,以及使用动态 SQL 参数来减少威胁。

为了防止您的网站被用于XSSXSRF攻击,请使用函数查找并删除用户提供的文本输入中的 HTML 标签。

创建用户定义函数

使用 SQLite 而不是其他小型数据库的好处是它可以通过创建自己的用户定义函数来与扩展 API 交互,从而具有灵活性。如果您熟悉在 Java 或 C 等语言中创建自己的函数,那么扩展 SQLite 数据库将不会很难。以下代码概述了如何使用 C API 实现这一点:

void test_function(sqlite3_content* tmp_value, int tmp_assign, sqlite3_value** values)
{
/* Respond back Text or reply */
    const char *tmp_string ="Test String - Hello World";

/* Set value to be returned */
sqlite3_result_text(tmp_value,tmp_string,strlen(tmp_string),SQL_STATIC);
}
Execute it by creating function using - sqlite3_create_function(db1,"test_function", 0,test_function);

事务和锁

事务和锁状态是 API 及其函数组成的一部分。

虽然很难完全控制,但锁和事务与 SQLite 和大多数数据库系统中的查询是相互关联的。更好的事务的关键在于程序员编写良好的 SQL 代码,确保其性能良好,并在旅途中处理可能出现的错误和问题,以便应用程序不会崩溃或让用户陷入困境。锁的另一个问题将涉及您需要的资源。有时,可能是因为代码编写不当,没有使用autocommit或持有对表和您过程另一部分的排他性锁,例如,您无法更新它。因此,对于程序员来说,评估、学习 API 以及了解锁定和事务策略如何工作以产生流畅和良好的应用程序非常重要。

默认情况下,SQLite 使用autocommit,其中事务周期开始和结束,由程序员和用于应用程序的语句控制。每个 SQL 命令都将在其自己的事务中运行,因为使用了autocommit。然而,在事务内部,特别是在使用begin命令时,程序员必须手动调用回滚或提交以更新数据库。有时,这种锁定策略可能会导致 SQL 违规或错误,这必须在应用程序的错误处理代码中处理。

在密码方面,作为程序员或设计师,不要将密码,如数据库密码,存储在任何可能被任何用户访问的纯文本或脚本中。例如,在指向 Web 服务器的目录中,源文件可能会被破坏。

应用程序的身份验证应在两个级别上进行,使用强密码格式,以确保访问不被破坏,尤其是在像间谍软件这样的技术下,它可能会破坏您的系统。当数据库授权条款提供不足的保护时,数据可以被加密,这是最初所需的。

事务 – 读取/写入

当在 SQLite 中使用SELECT语句时,它从默认的UNLOCKED状态移动到SHARED状态,一旦语句被提交,它就恢复到UNLOCKED状态。事务锁定状态有几种状态,锁定在autocommit开启或autocommit关闭的begin/end语句安排中有事务控制时起作用。当存在一些竞争时,事务锁定状态可能会从UNLOCKED变为SHAREDRESERVEDEXCLUSIVE

如果要进行更新,程序员可能会编写代码以使用EXCLUSIVE锁。这阻止了其他进程的更新,直到工作完成并释放锁为止。在这种情况下,程序员还必须编写代码并发布消息或写入日志文件;如果发生这种情况,审计员或数据库管理员将有一个应用程序生命周期的活动审计记录。这样做是非常好的实践。

为 SQLite 设计

通常,程序员会认为数据库系统庞大或者在企业环境中表现最佳,因此 SQLite 和移动环境也会一样。记住,当应用发布时,确保 SQLite 内置了一些基本数据供用户开始使用。确保数据可以轻松动态填充。这将形成优秀数据访问策略和格式的一部分,应该在所有应用中复制。

如前所述,数据安全是强制性的,并且必须考虑隐私和访问要求,包括加密形式,以保护信息。

在设计良好的 SQLite 数据库时,另一个重要因素是性能和软件在小型设备上高效快速工作的能力,而今天对它的需求更多。

使用如Appium等移动产品进行手动和自动测试是必须的,因为它可以发现相关错误、问题和问题,这些问题手动测试可能没有发现。SQLite 在你应用中的使用可以像你需要的那么复杂或简单,代码和专家的自由和可访问性都很丰富,以确保你的应用实现其目标。

摘要

在本章中,你学习了如何使用 SQLite 为应用设计数据库系统。你了解了如何接近设计细节,并概述了某些概念。下一章将向你展示如何管理 SQLite 数据库并利用这一功能。

第三章:数据库管理

在本章中,我们将向您介绍 SQLite 数据库的管理,并让您了解这个关系型数据库系统的不同组件,这些组件最适合移动或平板设备。SQLite 是一个嵌入式 SQL 引擎,它简单地读取和写入普通磁盘文件,而不是有一个单独的服务器进程。它是为此目的而设计的,并且维护起来更容易。

除了是一个优秀的程序员数据库外,SQLite 还是一个易于管理和维护的数据库。管理这个数据库不需要任何配置或设置。它附带了一个标准的 命令行界面CLI)客户端,可用于管理数据库(们)。

有许多与 SQLite 兼容的语言,这些语言更容易维护并添加新功能。

以下是一些 SQLite 的特性:

  • SQLite 是最容易学习的数据库之一,易于交互,并且能够从头开始构建新的数据库。

  • 它能够将数据库引擎本身集成到代码中,这对代码开发、性能和接口是一个巨大的提升。

  • 开始、学习、执行以及在实际操作中了解关系型数据库系统如何组合在一起,以及它是如何存储应用程序数据的,这些都非常容易。

在市场上,有各种各样的工具可以使 SQLite 的数据库管理更加容易使用,安装更加实用,并便于开发。在我们的案例中,仅将使用 命令行程序CLP)。

这些是市场上的一些工具:

  • RazorSQL,位于 www.razorsql.com/features/sqlite_features.html,是一款在浏览器环境中运行的定制软件。它可以突出显示语法,并提供一个编辑器来编写和更新代码,一些可视化管理员工具以及 SQLite 独有的功能。

  • 另一个工具是 SQLite Maestro,位于 www.sqlmaestro.com/products/sqlite/maestro/,这是一个针对数据库管理市场的优秀产品,旨在使用 SQLite 创建、更新和删除数据。例如,它包括数据库设计器、SQLite 语法检查、管理员工具和数据导出功能。

  • Navicat 是另一个 SQLite 数据库管理工具,位于 www.navicat.com/products/navicat-for-sqlite。他们的产品包含一些优秀的可视化工具、数据库维护功能、报表和数据导出等功能。

CLP 实际上是一个包含 SQLite 引擎的程序。CLP 既可以作为命令行工具,也可以作为交互式外壳运行。命令行模式是数据库管理员DBAs)可以使用它来为应用程序创建表、上传数据到骨架表以及修改信息以便进行开发、测试和发布的设施。要开始使用命令,在终端监视器中输入 sqlite3

管理数据库

如果您输入 sqlite3 <database name>,系统将加载到命名的数据库中,并准备好进行工作。例如,您还可以输入 sqlite3 –help,如以下截图所示,这将概述作为帮助一部分可用的命令。如以下截图所示,有多种选项可以帮助 DBA 或用户按需完成任务。在 sqlite3 中,要退出提示符,请输入 .exit 以离开程序。在终端提示符 $ 中,输入 sqlite3 –help 以获取命令列表,如此处所示:

管理数据库

前面的步骤是手动进行的,可以由数据库管理员使用。为了自动化数据库过程,Shell 脚本理想情况下可以使用该格式,这可以提高数据库性能。

创建数据库

首先,必须创建一个数据库。通过使用以下命令创建数据库,尽管数据库将被创建,但数据库中还没有实际存储任何内容。一旦创建,SQLite 数据库没有默认的存储位置。位置可能是您的家目录、工作目录或预先创建的数据库目录:

$ sqlite3 testdatabase.db

默认情况下,环境已经准备好,以便有效地为数据库对象,如前所述定义。SQLite 被设计为具有避免任何大小限制的独特策略。为了有一个易于适应设备内存并作为 32 位整数的策略是可行的,但这不是最佳选择。事实证明,当产品被推向极限并且可能利用安全漏洞时,这会引发问题。对象的默认设置很慷慨,对于大多数应用程序来说都是足够的。还有不同的设置语句,例如 SQLITE_MAX_COLUMN,它控制表、索引或视图中的最大列数。

只有在创建了表和索引之后,数据库的物理创建实际上才开始。这允许 DBA 在创建磁盘参数和分配之前更改不同的页面设置。此后,更改设置会更加困难。

创建表

要在新的数据库中创建表,请使用以下命令:

创建表

在运行上述命令创建数据库之后,执行create table temp语句以创建一个临时表。它有三个列,id是一个主键,其值会自动递增;name,是文本类型;以及address,也是文本类型。

插入数据

要将数据插入到新表中,请使用以下命令。这是一个简单的操作,将数据插入到左侧列出的表中,以及右侧相同格式类型的值和参数,或数据:

插入数据

使用两个列的数据(nameaddress)将数据输入到temp表中。请注意,对于id字段不需要提供值,因为 SQLite 会内部提供,并且自动递增其值。

选择数据

要从新表中选择数据,请遵循以下命令。这是一个简单的操作,用于获取信息并在屏幕上显示:

选择数据

temp表中选择了所有列的数据,因此使用了字符*,否则可以指定一个列名,只检索该列数据。

创建索引

要为temp表创建索引,这将允许使用id字段更快地进行选择,并且有少量的开销,这可能会被性能提升所超过,请使用以下命令:

创建索引

name列中创建了一个名为temp_idx的索引,这将允许以最小的数据访问开销更快地访问。

导出数据

要从 SQLite 导出数据,使用.dump命令,如下所示截图。不需要任何参数,可以以这种方式导出整个数据库。如果添加了一个参数,如表名,则只导出其内容。默认情况下,.dump命令将输出到屏幕。如果您想将输出定向到文件系统,请使用.output语句加上一个空格,然后是文件名,如下所示截图。

使用这些命令后,在当前目录中创建了一个文件。要返回到屏幕上输出数据,请使用.output stdout命令,如下所示。

使用这些方法可以提供更多的灵活性、控制和更好的输出格式:

导出数据

如前一个屏幕截图所示,输出到了temp.sql文件。执行了.dump命令,将所有数据库信息输出到temp.sql文件。要将输出返回到屏幕,请使用.output stdout命令。

查看数据库模式数据

SQLite 提供了一系列命令,作为命令集的一部分,以获取有关数据库内容的信息。例如,要获取表列表,使用.table命令。要查找特定的表名,使用一个%符号和文本作为模式来查找结果,例如,.tables [pattern],如下面的截图所示。通过发出.tables命令并将其附加一个%te%文本,是请求 SQLite 列出其数据库中所有名称中包含单词te(在我们的案例中是temp)的表,并且显示正确:

查看数据库模式数据

索引数据

在以下示例之前,已经创建了一个temp_idx索引,要获取temp表的索引列表,在sqlite3提示符下输入.indices temp,这实际上是.indices命令后跟表名,如下所示:

索引数据

使用前面的命令,可以看到temp表的索引。

模式数据

要查看数据库的模式,可以发出以下命令,.schema,但输入.schema <table name>命令以获取关于特定name数据库对象的详细信息。请参阅以下截图以获取更多信息:

模式数据

前一个命令显示了从数据库的temp集合的表和索引的输出。下一个命令显示了整个数据库模式:

模式数据

SQLite 主模式表显示了 SQLite 数据库上存在的表和索引。

备份数据库

备份 SQLite 数据库有几种方法。为了使其便携,请在 CLP 中使用.dump语句,它可以导出整个数据库和脚本到文件系统。以下是一个示例:

备份数据库

前面的语句显示了如何使用数据库名称调用 SQLite 并将输出管道传输到名为temp.sql的文件。

以下是将 SQLite 和备份交互式调用的另一种方法。

用户可以直接通过以下命令集导入数据:

备份数据库

以下命令将打开 SQLite 和temp.db数据库,并将temp.sql文件导入其中。在temp.sql文件中,将包含读取源文件并将数据导入数据库(现有或新版本)的脚本:

备份数据库

另一种方法是只需将temp.db文件复制到名为temp.backup的版本中,但上述方法更好且更便携,并且可能存在二进制兼容性问题,因为 SQLite 在向后兼容性方面并不享有很高的声誉。

数据库工具

SQLite 管理工具种类繁多,其中之一是 SQL Browser (sqlitebrowser.org/),它适用于不同的平台。数据库可以进行管理,表格可以导出或导入,查询可以创建、更新和执行。其他工具如下列出:

  • RazorSQL

  • Navicat

  • SQL Maestro

  • SQL Browser

  • phpSQLiteAdmin

  • SQLiteManager

  • SQLite Expert

另一个用于 SQLite 管理的先前或已废弃的项目是 phpSQLiteAdmin。该项目现已废弃,最后一次更新是在 2008 年。它可在 phpsqliteadmin.sourceforge.net/ 获取。phpSQLiteAdmin 是 SQLite 数据库管理的网络界面。它允许用户删除、创建和管理数据库,并查看数据库信息,如模式、表格、索引和文件元数据。市场上还有一个类似的项目,名为 Bitbucket(可在 bitbucket.org/phpliteadmin/public/ 获取)。

SQLiteManager 是一款可以管理数据库以创建、更新和导入或导出数据的产品;SQLiteManager 可在 www.sqlitemanager.org/ 获取。这是一个基于网络的 SQLite 管理工具。表格中的行可以管理,并且可以根据需要创建用户函数。再次强调,该项目和产品目前不活跃,自 2013 年以来没有更新。该产品现已迁移到 Bitbucket,不再作为 SQLiteManager 有效。然而,自 2013 年迁移到 Bitbucket 以来,没有更新。

此外,还有一个名为 SQLite Expert 的额外工具(可在 www.sqliteexpert.com/ 获取),它有个人版和专业版。例如,它内置了 SQL 查询构建器,提供了导入和导出数据的功能,以及数据编辑功能。

数据库文件信息

sqlite_master 视图概述了 SQLite 中所有数据库对象的详细信息。在 SQLite 中,数据库的最大大小为 2,147,483,646 页,每页 65,536 字节,或 140,737,488,224,256 字节(约 140 太字节),而 SQLite 数据库的最小大小是一个 512 字节的页面。查看哪些表格存在最好的方法是通过对主表执行 SQL 语句,如下面的命令集所示:

数据库文件信息

实际上,可以从 SQLite 网站下载 sqlite3_analyzer 程序。该程序执行许多功能,例如查询数据库文件,并以文本格式输出摘要,显示数据库结构、其环境、表格、索引、页面大小、条目、以字节为单位的存储、使用的页面、溢出页面和主页面上的未使用字节。

当分析数据库的资源、组件和结构时,可用的详细信息令人印象深刻且非常有用。

sqlite3_analyzer 程序也可以以多种方式使用,以利用从其使用中获得的统计数据。sqlite3_analyzer 是一个 TCL 脚本,可在 www.sqlite.org/src/artifact/8e50b217c56a6a08 获取。

摘要

在本章中,你学习了如何管理和维护 SQLite 关系型数据库系统,它以简单的方式向你展示了如何管理应用程序的数据库。本章介绍了 SQLite 数据库的一些基本元素。它涵盖了创建表和查看构成模式的表的必要要素。这些主题足以让你掌握这个主题并精通基础知识。本章涵盖了基本元素,并为管理这个易于使用的移动数据库提供了帮助。本章还总结了与其他市场上的数据库相比,管理 SQLite 的简便性。你可以在网上找到更多用于 SQLite 管理的工具。还有许多其他命令,本章并未全部以示例形式展示。这些都是使用和管理 SQLite 的一些方法。本章向你展示了当你学习一些命令时,你可以做到什么,以及它如何帮助使用这个简单、移动的数据库。

在下一章中,你将学习 SQL 的所有基本要素。本章将概述如何正确地在移动数据库上使用 SQL。它将向你展示如何使用 SQLite 的 SQL 方法与其他数据库相比,以及使用 SQLite 学习 SQL 的简便性。

第四章:SQL 基本知识

在本章中,你将了解 SQL 的所有基本知识。它将概述 SQL 的主要可能性以及如何在 SQLite 上正确使用。SQL 是使用 SQLite 的基础,也是利用 SQL 优势的必要条件。它在许多方面都相关,因为它是数据通过、查询和显示的方式,使用变量。

我们将讨论如何使用“having”之类的子句来使用该语言。一旦你了解了 SQLite 中 SQL 的基本用法,这将使整个主题变得更容易。

在业界,SQL 也被发音为sequel,并且是使用这些命令和语法的默认数据检索标准。本章中的说明将使用易于理解和遵循的风格和格式。它利用了重放代码、重复它并牢记它的想法,以增强你的知识和经验。

你还将看到可用于排序、校对和按需排序信息的各种数据检索选项和技术。本章中展示的示例将提供易于遵循和有用的指令,使用高级 SQL 命令。结果将快速,甚至瞬间即可获得,可以反复练习以获得必要的知识。本章将包含如customerssalary之类的表格以及不同的触发器名称和 SQL 语句。

本章中的示例将符合 ANSI 标准,并且应该与 SQLite、Oracle、Ingres、SQL Server、MySQL、MS Access、Informix、Sybase 以及其他 ANSI SQL 兼容数据库一起工作。本章旨在提供关键信息,这将提高你的技能。它还将作为一个简单的复习和提醒,让你回忆起最初学习的内容。

首先,SELECT语句是通用命令中最容易的一个,但也是协议的核心之一。它允许系统内的数据以用户请求的格式和风格可见,前提是它是语法正确的。

SELECT语句中存在许多子命令和子句,本章将讨论其中的一些。由于SELECT语句的重要性及其在数据选择方面的众多选项,它将成为本章的重点。作为一名开发者或数据库管理员,了解可能的选择总是有益的,这有助于编写高效的查询。本章将提供这方面的知识,并对专家来说,将是一个知识的更新。尽管 SQLite 命令在 Oracle 或 MySQL 中工作方式和外观相同,但实际上 SQLite 的一些命令是不同的。

让我们开始吧!

事务

数据库事务是一个包含多个操作的逻辑工作单元。根据定义,它将具有四个ACID属性:原子性一致性隔离性持久性

事务必须提供对执行工作的全面承诺感,或者是一种回滚而不完成工作的方式。它还必须保持每个事务与其他事务的独立和隔离,并确保事务完成,信息写入数据库。它还必须减少数据库的不一致性,并允许从任何故障中恢复的最佳和正确方式。

查询计划

当要执行查询时,数据库使用查询计划来构建数据路径,其中创建最佳和最有效的路由类型。如果有表连接、索引和表中的行数,则会准备使用不同算法的各种数学计算。当 SQL 存在问题,需要调试多个表连接和索引设置,以及遵循路径来解决数据或编程问题时,拥有执行计划是有用的。

除了纯文本格式的直接 SQL 语句外,还有一些语句将在 iOS 中使用,并封装在 Objective-C 或 Swift 等语言中。

当查询执行计划执行时,数据和信息仅用于调试,应作为指导使用。每个 SQLite 版本都将有不同的更新影响产品。计划的整体思想是概述 SQL 命令采取的策略路径。

需要使用一个名为EXPLAIN的关键字,或者是一个短语,即EXPLAIN QUERY PLAN,以获取表的详细信息。这些命令仅用于调试和分析。这些命令部分有文档记录,其行为并不总是 100%:

查询计划

接下来,我们看看带有salary选择的 SQL 语句将是什么样子。使用EXPLAIN QUERY PLAN命令与SELECT语句一起,基本计划概述了表的名称及其顺序。通过有效地学习查询执行计划,你可以了解 SQLite 如何访问你的数据,并看到它是如何提交的:

查询计划

EXPLAIN QUERY PLAN命令作为执行 SQL 查询的指导和计划。它将报告并提供与数据库索引如何有效使用来访问数据相关的信息。

系统目录也是所有表和索引的主列表位置。例如,sqlite_master表如下所示:

查询计划

SQL 基础

SQLite 还有一些其他用于 SQL 的功能,例如从列中查找最大的id,以及最后插入及其id,如下所示:

SQL 基础

带子查询子句的插入

INSERT语句是用来向数据库中添加数据的。然而,迄今为止的示例只展示了来自固定信息或程序变量的数据。还有另一种插入数据的方法,即基于选择标准和数据/列匹配从另一个表插入。这是一种带有子查询子句的插入;请参见以下示例:

SQLite> Insert into Salary values (Select id, name, salary from salary_import where name='Smith');

SQLite> Select * from Salary where name like '%smith%';

格式有多种变体,如前例所示。SQL 是灵活的,有选择不同数据和在 ID 的最后行上进行计算的选择。

使用子查询子句更新

如前几章所述,UPDATE语句用于从程序变量或固定数据中更改表中的现有数据。然而,还有另一种方法可以从具有匹配和链接关系的源表更新数据到目标表,如下所示。UPDATE语句将修改多个列。WHERE子句将确定哪些列需要更新。这是最容易理解和使用的 SQL 命令之一:

SQLite> Update salary = 15000
Where name='John Smith';

SQLite> Select * from Salary where name like '%smith%';

使用子查询子句进行选择

如前几章所述,SELECT语句用于从数据库的核心检索并显示信息给用户。SELECT语句是一个非常流行且功能强大的命令,具有各种选项和选择来检索数据。子查询子查询是原始 SQL 中的嵌套 SQL 片段,它嵌入在WHERE子句附近。子查询或子查询将仅用于检索与主选择查询通过特定列名链接的信息。

这些子查询子句可以用于DELETEINSERTUPDATESELECT SQL 命令中,例如使用=<>>=<=INBETWEEN等运算符。子查询有一些规则适用,例如,子命令的SELECT子句中必须只有一个列,除非在主 SQL 语句中选择了多个列。

子查询查询必须使用括号作为其语法的一部分,以概述子查询本身。查询的主体部分可以使用ORDER BY语法,但不能在子查询中使用。如果使用这些类型的查询返回多行,则必须使用IN等运算符。只要不是BETWEEN运算符本身,BETWEEN词可以在子查询中使用:

sqlite> SELECT * FROM PERSONNEL WHERE ID IN (SELECT ID FROM SALARY WHERE SALARY > 15000);

数据完整性

数据完整性在维护表和数据关系定义及保护方面非常重要。数据完整性有四种类型:用户定义的、引用的、实体的和域的。

掌握数据处理、数据库设计、开发和管理的技能对于确保使用 SQLite 构建的应用程序性能良好,并保持无数据崩溃、数据损坏和安全问题至关重要。

当设置列的数据类型时,这就是一种数据完整性的形式。可以通过仅允许某些值来增强数据完整性。

当设计一种机制来通过唯一的元组或行标识符维护表中的主键时,这被称为实体完整性。

当例如两个表通过一个公共列数据类型链接时,发生引用完整性。引用完整性确保数据被清理并正确链接。

默认值

列的 默认值 非常有价值,因为它强制数据完整性并确保在数据库中输入了值。这也意味着某些 SQL 语句比其他语句更短。一个没有添加列的标准语句类型是 id 字段,其中定义了主键,当使用 INSERT 语句时,不需要 id 字段,如下所示。

DBA 可以创建列以在数据库中自动存储 current_timestamp,这对于日志记录和时间戳很有用。

sqlite> INSERT into salary (name, salary, bonus) values ('John Smith',15000,2000); sqlite> SELECT * FROM salary;

id            name         salary    bonus
-----       --------     ---------  --------
1           Peter Jones   10000      3000
2           Sam Smith     15000      1000
3           John Smith    15000      2000

约束检查

为了确保正确的数据输入到表中的列,必须施加某些规则,这些规则被称为约束。这些规则强制数据准确性,限制损坏,并提高并维护数据可靠性。

在表级别,它将应用于整个表,但在列级别,它将仅应用于一个特定的列级别。它们的使用方法如下所示:

  • .UNIQUE 约束将确保列数据信息不重复

  • .PRIMARY 键,在 SQLite 中,每个数据行在表中都有一个标识

  • .NOT NULL 确保没有列存储了 NULL 值

  • DEFAULT 将设置一个默认值,当未指定或输入值时

外键

当两个或多个表需要在公共列上链接在一起时,这被称为 引用键外键。SQLite 支持关系完整性并支持外键约束,就像其他数据库一样。它通常由 DBA 设计,涉及一个列 ID,例如,以匹配第二或第三表上的 ID。

为了表现良好,表列和实际数据之间必须存在逻辑引用。SQLite 将使用外键作为创建表语句的一部分;以下是一个示例:

CREATE Table Salary (
id integer primary key,
name text,
salary
};

更新视图

视图 是一个命令,可以使用表的组合和连接来向用户或程序显示一组预定义的数据,如所需。实际上,它提供了数据的视图。您不能从视图中 DELETEUPDATEINSERT

由于视图是用一个特定的名称定义的,该名称存储在数据库中,因此它可以有效地作为表引用,作为要操作的语句的一部分。

如果在 createview 词语中存在如 TemporaryTemp 这样的关键字,那么该视图只能被那个数据库连接看到,并在连接关闭时被删除,因此得名 temp/temporary

当创建视图时引用数据库名称,它将位于该特定数据库中。

索引使用

在创建了一个具有其列和数据类型的表之后,它几乎可以投入使用。数据链接的主要列已经完成,但根据数据库管理员(DBA)的定义,它还不完全准备好。相反,可以创建一个索引来加速 SQL 查询,并作为 SQLite 将用作快速获取信息方式的特殊查找表。

索引有一个数据指针,它将快速引用数据并将其返回,从而使得访问更快,通常没有太多开销。根据定义,索引确实有其自身的开销,但索引的开销被性能和效率的获得所掩盖。这对于移动应用程序可能很有用,因为它们资源有限且网络访问受限。

作为例子的数据库索引类似于书中的索引,你可以找到你想要的内容,因为你知道它是什么,只需打开书到正确的页面,在阅读索引之后。

索引在数据输入上较慢,但在SELECT查询上较快,无论是否有WHERE子句。一旦创建了索引,也可以将其删除,而不会影响表的核心数据。以下是一个简单的例子,展示了在customer表上创建了一个名为table_index_name的索引:

CREATE INDEX table_index_name ON customer;

第二个例子展示了如何创建一个索引来引用一个名为salary的列,该列在许多查询中被多次使用:

CREATE INDEX table_index_salary ON customer (salary);

在这里,一个索引将加速访问。在customer表上创建了一个名为table_index_salary的索引,它是在salary列上创建的。

也有被称为组合索引的索引,实际上是为了在数据库中索引多个列以获得进一步的性能提升,但也会在数据输入上产生开销。如下所示,创建了一个索引并将其链接到两个列:salarybonus。与其有两个索引并带来更多开销问题,一个组合索引可能更好,因为它是一个索引,但引用了两个列:

CREATE INDEX table_index_salary ON customer (salary, bonus);

在创建索引时,数据库服务器还会创建隐式索引,这些索引是自动的。如果作为数据库管理员(DBA),你想查看它们,请使用以下示例:

sqlite> .indices customer;

触发器

触发器是使用 SQL 命令与数据库高效交互的有效方式。它们快速,并且嵌入在创建trigger命令中。

触发器由触发器名称、涉及到的表引用、时间事件(如之前或值更改之后)、操作类型(如插入、更新或删除)以及各种表和列组成,以完成操作。

语法必须正确,测试应确保更新和更改是正确的,以确保数据并发性和稳定性,没有损坏。

这个触发器被称为update_customer_trigger,它对customers表执行UPDATE查询。更新将影响tel_no列。因此,当前的电话列tel_no将被更新,其中它将等于新表中的值,以及其列tel_notel_no = new.tel_no),其中客户名称的链接(customer_name)等于old.name列。

更新的触发器必须使用表中的特定列,这些列是预定义的,与insertdelete列不同。

sqlite> select sql from sqlite_master where name='update_customer_trigger';

CREATE TRIGGER update_customer_trigger UPDATE OF tel_no ON customers    BEGIN     UPDATE orders SET tel_no = new.tel_no WHERE customer_name = old.name;   END

同步写入

同步写入是 SQL 引擎的一部分,它将确保根据事务原因和数据库工作方式,将数据更改写入磁盘区域。在 SQLite 的情况下,这些操作在不同的状态或设置下进行,例如NORMALFULLOFF。出于性能原因,DBA 可以根据需要关闭 SQLite 的提交。

OFF设置快速执行任务,几乎没有减慢速度,最小化中断,并提高性能。然而,在数据库崩溃的情况下,数据完整性将保持良好,但在系统崩溃和断电的情况下,数据库本身损坏的可能性很大。虽然可以取得性能上的提升,但这也伴随着与此行动相关的风险。

FULL设置必须确保在继续之前,数据被正确且及时地保存到磁盘上。这种方法对性能不利,但是最健壮和最安全的。如果出现数据损坏或系统崩溃,用户可以确信不会发生数据库损坏。

NORMAL设置会定期减慢速度以保护数据并将事务提交到磁盘。数据库崩溃或断电可能会损坏数据库,但更严重的硬件错误可能更糟糕。

数据库锁定和死锁

当一个或多个操作或 SQL 语句与其他进程或操作同时竞争数据访问和表更新或操作时,就会发生死锁。由于它与事务一起工作,一个进程无法前进或完成,因为另一个进程或操作正在持有资源并等待,因此形成了死锁。

因此,在数据库中,一个进程可能会尝试更新某个记录,而另一个进程则希望更新同一行中的某些数据,或者是在事务发生时另一个表中的冲突。必须有一种形式的数据锁定机制来管理和减少冲突。可以在事务周围的代码中添加一个重试指示器,例如三个,如果发生死锁,它将重试,并在第三次尝试后回滚或给用户一个重试的机会。

死锁是多线程和多进程操作系统中的常见现象,这些系统正在执行各种任务,并试图以积极的结果完成。

以下示例展示了 SQL 事务最终会导致死锁的情况。在这种情况下,两个事务/会话都将处于死锁状态。会话 2 将尝试向数据库插入/写入并创建锁定以获取独占权限来保护,并确保它可以无问题地插入记录。会话 1 也尝试写入,这也导致了死锁情况。实际上,我们有一个会话 1会话 2 都不想失去访问或控制权,直到对方离开,这导致死锁继续,如下所示:

会话 1 会话 2
sqlite3> sqlite3>
sqlite3>insert into temp(name,address) values('Gene','London');
sqlite3> select * from temp;
sqlite3> commit;
SQL 错误信息:数据库锁定
sqlite3> insert into temp(name,address) values('Gene','London');
SQL 错误信息:数据库锁定

FMDB SQLite 包装器

除了使用标准的 SQL,Objective-C 编写的 FMDB SQLite 包装器,对于那些喜欢使用替代且更简单方式与 SQLite 交互的人来说,可能会有所帮助。

有关 FMDB 规范和代码示例的更多信息,请参阅 github.com/ccgus/fmdb

FMDB 中有三个主要类:

  • FMDatabase:这是执行您的 SQL 语句的单个 SQLite 数据库。

  • FMResultSet:这将保存并显示从 FMDatabase 得到的输出和结果。

  • FMDatabaseQueue:如果您想在多个线程中执行查询和更新,这个类将使您能够更新和使用许多线程。

数据库创建和打开

数据库被定义并分配到位置和目录:

FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/atmp.db"];

要与数据库交互,您必须连接并打开它,如下所示:

if (![db open]) {     [db release];     return; }

iOS 中的 SQL

要选择数据,可以使用 executeQuery 等方法返回 FMResultSet 对象(如果成功),或失败时返回 0。有如 lastErrorMessagelastErrorcode 等方法可以用来确定查询是否成功或失败:

FMResultSet *s = [db executeQuery:@"SELECT * FROM aTable"]; while ([s next]) {     //retrieve values for each record }

对于多行,必须使用 [FMResultSet next] 来查看或读取查询返回的值,即使记录集只有一个,例如。

以下命令展示了如何使用 FMResultSet 来选择所需的多个查询:

FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM aTable"]; if ([s next]) {     int totalCount = [s intForColumnIndex:0]; }

FrmresultSet 为程序员提供了几种检索方法;以下是一些示例:

  • intForColumn:

  • longForColumn:

  • longLongIntForColumn:

上述一些方法默认将具有 {type}ForColumnIndex: 变体,它将用于根据行中列的位置而不是名称本身来获取数据。

之前使用 FMDatabase 的代码来自 GitHub,是这些类型操作的标准代码。它已被用于提高与 SQLite 交互的便捷性,而不是传统的标准方法。

摘要

在本章中,你学习了与 SQLite 数据库相关的 SQL 基础知识,以及构建 SQL 语句和与 SQLite 及 iOS 交互所需注意的事项和所需知识,作为基本入门。

在下一章中,你将了解暴露 C API 的所有内容,它在 iOS 中的影响和用途,以及它是作为 SQLite 一部分如何工作的。下一章还将提及 C API 是 SQLite 的核心,以及它的使用方式。

第五章。公开 C API

在本章中,你将了解有关C APIC 应用程序编程接口)的所有内容,并通过代码在你的应用程序中使用它。通过拥有超过 200 个 API 调用到这个轻量级、小型且不断扩展的 API 集,SQLite 将让你惊讶于它如何实现你想要的移动和灵活的数据库。

你将查看一些语法和用法,并了解如何通过使用其庞大的 API 调用库来扩展 SQLite 的功能。

SQLite C 组件的功能

SQLite 是用 C 语言编写的,其创建者已经使它能够公开,并通过提供一个 API(C API)增强了其功能。一般来说,SQLite 有许多不同的 API 调用,例如,大约有 200 个 API 用于不同的功能。作为程序员,你可能觉得难以接受,但 API 是为特定任务设计的,例如,sqlite3_reset()函数清除与 SQLite 预编译语句关联的对象,并将其重置到其原始状态和值。

首先,两个核心对象是数据库连接和预编译语句对象。函数的顺序和类型可以给你一个如何编写 SQL 事务连接数据库、创建表和索引以及用insert语句填充它的概念。这些函数构成了 SQL-C 接口函数的主要元素,允许数据在代码和 SQLite 之间连接和传递。

sqlite3_open()

sqlite3_open(const char *filename, sqlite ** Db_name)将打开位于您选择位置的 SQLite 数据库文件,并返回数据库连接对象,该对象将被其他 SQLite 组件或函数使用。

在进行任何其他操作之前,需要sqlite3_open()函数来建立连接。它将使其他操作得以进行。

如果在sqlite3_open函数中,文件名不包含NULL,则函数将使用提供的值,或者如果不存在数据库文件,SQLite 将尝试使用该名称打开一个新的数据库。一旦通过sqlite_open()函数建立了数据库连接,就可以执行sqlite_prepare()等命令。以下是sqlite3_open()的一个示例:

sqlite3_open()

sqlite3_prepare()

使用新的数据库连接,我们将获得一个指针地址,该地址将作为sqlite_prepare()命令的输入。语句将编译源 SQL 语句到目标代码。sqlite3_prepare()函数的功能是绑定并设置相关参数,将查询字符串作为数据处理的一部分链接起来。以下是sqlite3_prepare()过程的简要示例:

sqlite3_prepare()

sqlite3_step()

sqlite3_step() 语句将对之前 sqlite3_prepare() 语句生成的输出对象代码进行分析、检查和评估。它将执行一个 prepare 语句并返回一个 SQLite 状态码。如果有数据,则返回 SQLITE_ROW 状态码。当语句执行完毕时,将返回 SQLITE_DONE 状态码。任何其他返回值都将被视为错误。SQLite3_step() 必须重置后才能再次使用。

此方法主要用于 SELECT 语句。其他语句,如 DELETEUPDATEINSERT,将从第一条记录执行到最后一项完成:

sqlite3_step()

sqlite3_column()

随着 SQLITE3_prepare 语句的评估,SQLITE3_column 语句将显示结果集中的一个单独的列。SQLITE3_columnSQLITE API 中执行占位符功能,并且是其他各种函数的中心点,例如 SQLite_column_count()

有关更多信息,请参阅以下内容:

sqlite3_column()

sqlite3_finalize()

如其名所示,此语句将最终化并密封所有预准备语句。一旦执行了 sqlite3_finalize 语句,任何内存都将被释放,内部进程资源也将被释放。一旦完成,该语句就不能再被重用,并且在内部也不有效。有关更多信息,请参阅以下命令:

sqlite3_finalize()

sqlite3_close()

这是最后要执行的部分,即 sqlite3_close 命令,它将使用数据库连接的指针和引用关闭数据库,并且必须在关闭连接之前完成之前创建的预准备语句。

如前所述,为了在 SQLite 或任何其他数据库中调用或运行 SQL 语句,您必须连接到数据库,并在完成工作后断开连接。

之前的 SQLite_open() 语句是直接使用 C API 而不涉及 Swift 语言实现的一种方式。以下是在 C API 和 Swift 中使用打开数据库语句的两种方法。有两种类型的处理方式:

  • 使用 C API 和打开数据库语句

  • 使用 Swift 和打开数据库语句

使用 C API 和打开数据库语句

看看以下代码:

var db1 = SQLiteDatabase();
db1.open("/path/to/database1.sqlite");

定义了一个名为 db1 的变量来调用 SQLiteDatabase() 函数。然后使用括号内的数据使用 db1.open() 方法指向 database1 数据库,如前述代码所示。

使用 Swift 和打开数据库语句

使用 Swift 打开数据库的另一种方法是:

let datadocuments = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String

let databasepath = documents.stringByAppendingPathComponent("tester.sqlite")

// open the database

var databasedb: DBPointer = nil

if sqlite3_open(path, &databasedb) != SQLITE_OK
{
     println("error opening database")
}

请记住,对于 Swift,您必须导入 sqlite3.h 文件并将 libsqlite3.0.dylib SQLite 库添加到您的项目中。

要将 libsqlite3.0.dylib 添加到您的项目中,请按照以下步骤操作:

  1. 在项目编辑器中选择目标和框架。

  2. 在编辑器的顶部点击构建阶段,并打开包含库部分的链接。

  3. 点击+以添加框架,或者在我们的情况下,添加libsqlite3.0.dylib SQLite 库。使用 Swift 与开放数据库语句

  4. 使用NSSearchPathForDirectoriesinDomains搜索来设置datadocuments变量,然后设置databasepath变量作为sqlite文件的存放位置。

  5. 设置一个名为databasedb的变量,并执行检查以查看带有输入参数的sqlite3_open()函数是否实际打开数据库,否则显示错误信息。

SQLite 的美丽之处在于其灵活性和产品的扩展性,包括可扩展的 SQL 功能,如排序序列,以及使你的应用程序与众不同和独特的 SQL 函数。改变的范围和扩展应用程序的能力正在增长。

你构建的扩展可以链接到你的应用程序中,你可以使用SQLite_extension_init函数作为指针或地址来确保名称不冲突。

SQLite 扩展被归类为DLL(动态链接库——一组在需要时由大型应用程序使用的程序)。

根据定义,DLL 需要入口或起始点来与程序交互。这是进程附加到 DLL 并建立连接或交换信息和使用功能的地方。入口点函数用于在交互时执行清理任务或初始化。当进程使用入口点函数时,它可以用于分配内存或虚拟地址空间。

SQLite 可以使用加载扩展,这些扩展是在 SQLite 外部编写的,根据需要测试和部署。一旦开发完成,这些扩展可以轻松地链接到 SQLite。如果 SQLite 没有某些功能,第三方可以开发它,并将其提供给特定行业的潜在客户或用户,例如。

当为 SQLite 创建扩展时,每个操作系统的扩展都不同:

  • 一些 Unix 系统使用.so文件扩展名

  • Windows 系统使用.dll扩展

  • OS X(Mac)系统使用.Dylib扩展

这显示了该软件的巨大灵活性,可以满足各种操作系统,因此允许 SQLite 数据库应用于不同的系统和技术。

load_extension()

load_extension(X,Y)函数是另一个功能强大的函数,允许加载函数/扩展。其方法与sqlite3_load_extension() C 接口类似。这两种方法都使用入口点,需要一个名称作为标识符。可以传递空指针作为输入参数。

有一些更改数据库但不返回任何结果的命令,例如Update语句。执行此任务的函数是sqlite3_exec()。这种方法更快,且学习或执行都不困难。

sqlite3_exec()

sqlite3_exec() 过程包含一个指向打开数据库的指针,一个或多个 SQL 语句,以及一个使用指向回调函数的指针作为其功能的一部分。它将使用一个或多个 SQL 语句与一个以 null 结尾的字符串结合进行处理。查询的每一行都将有一个指向回调函数的指针。作为回调函数的第一个参数的一部分,还将发送一个指针。包括一个指向错误字符串变量的指针。

sqlite3_config()

sqlite3_config() 函数的功能允许在全局范围内进行更改。必须在打开数据库之前调用 sqlite3_config()sqlite3_config() 接口将允许调整 SQLite 的内存分配,并为整个过程生成错误日志。它设置并配置 SQLite 库,控制内存分配和相关资源的许多方面。

为了扩展 SQLite,需要进一步研究并使用 sqlite3_create_collation()sqlite3_create_function()sqlite3_create_module()sqlite3_vfs_register() 等函数和例程,根据需要作为改进产品功能的一部分。这些系统的维护将限于那些了解和使用该技术的人。

以下是一些使用 selectupdatedeleteinsert 命令结合 Apple 的新语言 Swift 使用数据库函数的示例。

如前所述,存在不同的 SQLite 包装器,其中一些专门为 Swift 编写(不多),但最常见的是 FMDB,它已被用于不同的应用程序测试:

  1. 为了将 Objective-C 引入 Swift,需要一个“桥接头”,即 sqlite3.h。要使用此头文件,请使用以下命令:

    #import <sqlite3.h>
    
  2. 如前所述,将 libsqlite3.0.dylib SQLite 库添加到您的项目中。

  3. libsqlite3.0.dylib 库添加到项目后,下一个任务是创建数据库。

  4. 接下来,使用 sqlite3_exec 功能执行 create table... SQL 语句,例如,在使用 Swift 的过程中:

    if sqlite3_exec(databasedb, "create table if not exists test table (id integer primary key autoincrement, name2 text)", nil, nil, nil) != SQLITE_OK {
        let errmsg = String.fromCString(sqlite3_errmsg(db))
    
        println("error creating new table: \(errmsg)") }
    
  5. 下一个要使用的语句是 Insert 语句,用于将数据输入到新创建的 test 表中。以下信息将展示如何准备、绑定和执行 SQL 语句。将使用 sqlite3_prepare_v2 函数准备 SQL,使用占位符 ? 来绑定所需值:

    var statement: DBPointer = nil
    if sqlite3_prepare_v2(databasedb, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK
    {
        let errmsg = String.fromCString(sqlite3_errmsg(databasedb))
               println("error preparing insert: \(errmsg)")
    } 
    
    if sqlite3_bind_text(statement, 1, "data", -1, SQLITE_TRANSIENT) != SQLITE_OK
    {
        let errmsg = String.fromCString(sqlite3_errmsg(databasedb))
        println("failure binding record data: \(errmsg)") }
    
    if sqlite3_step(statement) != SQLITE_DONE
    {
        let errmsg = String.fromCString(sqlite3_errmsg(databasedb))
        println("failure inserting record data: \(errmsg)") }
    
  6. 可以使用一个常量 SQLITE_TRANSIENT 作为以下过程的组成部分:

    let SQLITE_STATIC = sqlite3_destructor_type(DBPointer(bitPattern: 0))
    let SQLITE_TRANSIENT = sqlite3_destructor_type(DBPointer(bitPattern: -1))
    

这是使用这些变量的标准方式。有时,如果它们没有作为 .h 文件的一部分或在下述部分中定义,则这些变量可能不起作用。由于“不安全的指针转换”,它们在 Swift 中不受支持。

准备语句

作为 prepare 语句的一部分,使用 sqlite3_prepare_v2 的功能与 SQL 语句一起使用,使用问号 (?) 作为占位符来绑定输入值。以下示例展示了这一点:

var statement: DBPointer = nil
if sqlite3_prepare_v2(databasedb, "insert into testtable (name) values (?)", -1, &statement, nil) != SQLITE_OK
{
    let errmsg = String.fromCString(sqlite3_errmsg(db)) println("error preparing the insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "Bind1", -1, SQLITE_TRANSIENT) != SQLITE_OK
{
    let errmsg = String.fromCString(sqlite3_errmsg(db)) println("failure binding this statement: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE
{
    let errmsg = String.fromCString(sqlite3_errmsg(db)) println("failure on inserting data : \(errmsg)") }

标准是使用 SQLITE_STATICSQLITE_TRANSIENT 作为设置,如下所示:

#define SQLITE_STATIC((sqlite3_destructor_type)0)
#define SQLITE_TRANSIENT((sqlite3_destructor_type)-1)4

在 Swift 2 中,代码可能会有所改变,如下所示:

"Internal let SQLITE_STATIC = unsafeBitCast(0, sqlite3_destructor_type.self) internal let SQLITE_TRANSIENT = unsafeBitCast(-1, sqlite3_destructor_type.self)"

接下来,让我们使用一个 NULL 值执行一个 insert 语句来证明 SQL 确实是有效的:

if sqlite3_reset(statement) != SQLITE_OK
{
    let errmsg = String.fromCString(sqlite3_errmsg(databasedb))

    println("error resetting prepared statement: \(errmsg)")
}

if sqlite3_bind_null(statement, 1) != SQLITE_OK
{
    let errmsg = String.fromCString(sqlite3_errmsg(databasedb))

    println("failure binding the null value: \(errmsg)")
}

if sqlite3_step(statement) != SQLITE_DONE
{
    let errmsg = String.fromCString(sqlite3_errmsg(databasedb))

    println("failure inserting null: \(errmsg)")
}

如前所述,SQLite 可以通过允许每个 SQL 语句只准备一次、评估、执行然后销毁来工作,但它也提供了使用如 sqlite3_reset()sqlite3_bind() 函数之类的例程来准备相同的系统并多次评估不同时间的功能。SQLite 是一个良好且功能齐全的数据库,无需任何调整即可适用于不同的应用程序。

以下代码用于在完成工作后关闭数据库:

if sqlite3_close(databasedb) != SQLITE_OK
{
     println("error closing the database")
}databasedb = nil

这是具有内置 SQL 功能的语言的优势。

本章中的信息主要集中在 C API 的功能上。今天的开发者将根据需要扩展并使用不同类型的功能,为他们的应用程序嵌入 Swift、Objective-C、Java 或其他语言的使用。

摘要

在本章中,你学习了如何扩展 C API 并生成代码,这些代码可以用来构建一些有趣、激动人心、新颖和智能的数据驱动应用程序,并促进 SQLite 的使用。所使用的语言是 Swift。在下一章中,你将简要了解如何使用 Swift 与 IOS 和 SQLite,以及如何安装 Xcode 并与 Swift 和 SQLite 库一起工作。

第六章。使用 Swift 与 iOS 和 SQLite

在本章中,你将了解如何使用苹果公司新推出的编程语言Swift。这是一种由苹果公司创建的新语言,具有非常强大的功能来执行各种任务,并且现在已开源。苹果公司发布了它,并且它发展得如此迅速,以至于在接下来的几个月和几年里,它将成为使用苹果设备编码的事实标准。你将看到 Swift 如何与 iOS、Xcode 和 SQLite 协同工作。

自从 Swift 在 2014 年旧金山的 WWDC 上宣布以来,这已经是一次非凡的旅程。2015 年,苹果宣布 Swift 将开源。这种语言本身允许你轻松编写高级代码,甚至低级代码。它是 Python、C 和 Objective-C 等语言的集大成者,使其更快、更简单,并且可在多个平台上使用。

你能想象未来几年会发生什么吗?设计模式和技能正在快速发展,应用程序将使用新语言重写和部署。

我们将向您展示如何安装 Xcode 以使用 Swift 和任何 SQLite 库。我们将提供一些示例,说明如何使新语言与 SQLite 和 Xcode 协同工作。本章中提供的示例和信息将帮助您作为初学者掌握学习这种新语言并获得新技能。

基本要求

所有#Apple 开发都是在 Mac 上完成的。你需要以下内容:

  • 一台运行 Maverick 或 Yosemite 操作系统的 MAC 电脑

  • Xcode 应用程序开发环境

  • 对面向对象编程有良好的理解

  • 对 Swift 语言有基本理解,请参阅 Swift 参考指南

注意

如需参考信息,您可以查看developer.apple.com/library/ios/navigation/#section=Resource%20Types&topic=Guides上的Apple Developer Guide

对学习和提升技能持有积极的态度非常重要。

使用 Swift 启动 Xcode 项目

Xcode 受到了发布修复和 Swift 语言的增强影响。因此,有时之前容易工作的代码现在需要一些编码更改,编译器才会满意。这对于新语言不断变化的代码库来说,是一直都会发生的事情。

首先打开 Xcode。最好的 Xcode 版本是最新版本,可在苹果 App Store 的developer.apple.com/xcode/download/下载。安装 Xcode,设置完成后,启动 Xcode 并按照以下步骤操作:

  1. 创建一个新的项目(Cmd+Shift+N)。

  2. 在模板选择器中,确保iOS | Application被选中。选择Single View Application模板以开始过程:使用 Swift 启动 Xcode 项目

  3. 然后你会被提示添加项目名称,所以添加一个像Test Swift Project这样的名称。

  4. 接下来,添加公司名称为Voxstar Ltd或你的公司名称。

  5. 接下来,添加组织者标识符,在我们的例子中是com.voxstar.testswiftproject,这将标识你的应用程序名称,并且这就是它将被 Apple 识别的方式。

  6. 接下来,对于计算机语言,选择 Swift 而不是 Objective-C,这是我们本章所使用的。

  7. 对于设备,选择iPhone,同时确保未选择使用 Core Data选项。以下截图作为示例:使用 Swift 启动 Xcode 项目

  8. 点击下一步按钮继续此过程。之后,你必须存储项目文件的地址;我们建议你使用存储主.swift目录的位置,如下面的截图所示。对于本例,使用Documents目录,选择并点击下一步,将创建一个名为Test Swift App的新目录。以下截图显示了目录和项目信息:使用 Swift 启动 Xcode 项目使用 Swift 启动 Xcode 项目

  9. 一旦点击创建按钮,项目详情页面就会显示,如下面的截图所示。Xcode 使用一组标准文件、模板和组件作为其一部分:使用 Swift 启动 Xcode 项目

  10. 要显示使用 iPhone 的标准应用程序的外观,请点击播放按钮,并观看默认屏幕和 iPhone 6 模拟器的输出:使用 Swift 启动 Xcode 项目

然而,Swift 应用程序的第一个主要入口点是AppDelegate.swift文件。此文件位于应用程序目录中。在应用程序目录下,将有一个以应用程序命名的目录,这就是AppDelegate.swift文件所在的位置。在 Xcode 中点击它以打开,你将找到一系列信息。这些信息将从使用你的姓名和公司详情作为设置部分的标准注释开始。

此后的主要信息是import UIKit语句。如果你之前使用过 Objective-C 进行开发,这个语句将非常明显、非常熟悉且易于理解。

UIKit 将提供管理并构建这些 iOS Swift 应用程序的基本基础设施和骨干。它将包含必要的用户界面和其他架构,甚至可以处理和与应用程序的其他部分进行交互。它还支持基于运动的事件处理和触摸事件处理。

它还将支持处理网页和文本内容的同时,提供 iCloud 支持的模式。它还将支持 Apple 推送通知服务。更多详细信息可以在开发者 Apple 网站上获得:

使用 Swift 启动 Xcode 项目

与 Objective-C 或其他标准编程语言不同,Swift 没有 main 函数或文件。相反,你只需在主 Swift 文件中提及 @UIApplicationMain 语句,所有相关组件都会被包含进来。这一行代码可能永远不需要更改,除非有重大更新或更改。

使用 SQLite 3 库

在开始编码之前,您必须为 SQLite 添加一个特定的库。在 Xcode 中,确保选择并可见 通用 选项卡。在页面底部,寻找 链接的框架和库 部分。查看并点击带有加号图标的图标,如下面的截图所示:

使用 SQLite 3 库

将会弹出一个模态窗口;请输入单词 sqlite,然后从信息列表中选择 libsqlite3.dylib 选项,如下面的截图所示:

使用 SQLite 3 库

选择后,点击 添加 按钮继续。

作为本章的一部分,我们将使用 FMDB 和围绕 SQLite 的 Objective-C 包装器来展示使用 Swift 的数据库 SQLite。FMDB 代表 Flying Meat Database,它易于与 SQLite 交互,实际上可以节省时间和精力。例如,FMDB 将链接到一个 SQLite 数据库,并用于执行 SQL 查询。输出是 FMResultsSet,它显示了在 FMDB 上执行的查询结果。

注意

FMDatabaseQueue 类用于处理更新、查询和多重线程。

将使用 FMDB 方法在名为 Mortgage 的表上执行 InsertSelectDeleteUpdate 的 SQL 命令。Mortgage 表将有一个 名称 字段和一个 抵押卷号 字段,用于账户详情,作为一个非常简单的例子。

以下截图是使用 Xcode 内部的视图控制器场景工具创建的基本屏幕布局的实际用户设计。这将概述并显示在按钮被点击时将遵循和执行的操作:

使用 SQLite 3 库

有许多工具可以管理 SQLite 数据库,其中之一是 Firefox 浏览器中的 SQLite Manager Add-on,用于管理数据库。该插件可以从 addons.mozilla.org/en-US/firefox/addon/sqlite-manager/ 获取。

该插件产品为管理员提供以下一些功能:

  • 管理您机器上的 SQLite 数据库

  • 获取数据库对象的树形视图

  • 同时还有一些易于管理且有用的对话框,例如触发器、视图和表

  • 执行 SQL 查询的平台

  • 以 UTF-8/UTF-16 格式导出表或视图

  • 执行 选项卡中也可以执行多个 SQL 语句

打开 Firefox 并从上述链接安装扩展。以下截图显示了扩展的安装方式:

使用 SQLite 3 库

当你点击立即安装按钮时,插件将被安装。然后转到工具 | 菜单选项,你将找到SQLite 管理器。一旦点击该选项,就会出现以下屏幕:

使用 SQLite 3 库

为了向系统中添加数据,必须创建数据库。

当你点击立即安装按钮时,插件将被安装。一旦转到工具 | 菜单选项,你将看到SQLite 管理器选项。当你点击该选项时,就会出现以下屏幕。

创建新的数据库并确保为这个小型测试应用程序使用 SQLite 创建一个表。在这个场景中,我们有一个名为 Mortgagedata.sqlite 的数据库,一个名为 Mortgage_data 的表,包含两个字段:mortgage_rollnomortgage_name

下一个截图显示了在 Firefox 中调用SQL 管理器的屏幕:

使用 SQLite 3 库

当你点击SQL 管理器选项来创建数据库时,会弹出一个窗口,用户在此输入数据库名称,如下截图所示:

使用 SQLite 3 库

接下来,在数据库创建后,用户必须选择一个磁盘目录来存储数据库,如下截图所示:

使用 SQLite 3 库

接下来,需要创建一个表,如下截图所示,包含两行:

使用 SQLite 3 库

如前截图所示,这是在进一步工作之前表结构的样子。

接下来,需要创建一个类,这是一个 NSObject 的子类。将此类命名为 Mortgage_data 并根据此测试场景的要求设置其属性。这些属性将构成数据库模式以及你小型数据库和表的基础:

Class Mortgage_data: NSObject {
    Varmortgage_rollno: String = String()
    Varmortgage_name: String = String()
}

使用 FMDB

FMDB 是一个基于 SQLite 编写的 SQLite 库,用于简化数据库操作。

由于 FMDB 是在 Objective-C 中构建的,因此需要一个桥接头才能将其与简单应用程序链接起来。必须包含一个 .h 文件,即 FMDatabase.h

这是为了确保 Objective-C 和 Swift 技术的链接能够产生我们想要的结果。接下来,我们需要在 SQLite 管理器中创建数据库并将其复制到正确的位置。

在以下代码中,我们展示了复制数据库的函数。在这个例子中,我们需要创建并使用一个名为 copyFile 的函数,该函数将文件复制到应用程序的文档目录。例如,applicationDidFinishLaunch 方法通过将数据库名称作为要求参数的一部分传递给 AppDelegate 来与 AppDelegate 一起工作。

请参阅以下类:

class func copyFile(fileName:NSString){
    var database_path:NSString=getPath(fileName)
    var MortgageManager=NSFileManager.defaultManager()
    if !MortageManager.fileExistsAtPath(database_path){
    var fromthePath:NSString= NSBundle.mainBundle().resourcePath.stringByAppendingPathComponent(fileName)
    MortgageManager.copyItemAtPath(fromPath,toPath:database_path, error: nil)
}
}

当使用 FMDB 与 SQLite 交互的方式时,创建了一个名为ModelManager的类作为NSObject{}的一部分,以便在其中驻留或插入各种功能。这是强制性的,并在下一个代码片段中展示。

在以下代码中,您将看到在数据库对象被复制之后,需要对其进行初始化,必须为 Swift 文件命名并添加到ModelManager中,并且必须在class块之外定义ModelManager类型的共享实例,如下所示:

let mortgage_instance=ModelManager()

然后,为 FMDB 设置数据库对象,即FMDatabase对象,并与数据库对象一起设置和重置,如下所示:

var database:FMDatabase?= nil
class var instance:ModelManager{
mortgage_instance.database=FMDatabase(path:Util.getPath("Mortgagedata.sqlite"))
var Mydatapath=Util.getPath("Mortgagedata.sqlite")
println("The Current Path is> : \(Mydatapath)")
return mortgage_instance
}

下一个步骤是使用以下命令查询数据库,即insert命令,作为一个示例,它被分配的值Mortgage_Inserted所包裹。其他类,如ModelManager,将添加Mobile_data方法。然后ModelManager方法尝试通过打开方法,即FMDatabase类,来打开Mortgage数据库。接着分配并使用executeUpdate方法作为FMDatabase类的一部分,以推送和传递 SQL 查询和输入参数。为了完成这一部分操作,使用close方法。以下代码展示了如何连接数据库:

func addMortageData(Mortage_Data:Mortgage_data)-> Bool {
        mortgage_instance.database!.open()
        let Mortage_Inserted= Mortgage_instance.database!.executeUpdate("INSERT INTO Mortgage_Data (mortgage_rollno, mortgage_name) VALUES (?, ?)",withArgumentsInArray:[Mortgage_data.mortgage_rollno,Mortgage_data.mortgage_name])
        mortgage_instance.database!.close()
        return isInserted
    }

Insert Button有一个动作方法;调用此方法通过Mortage_data类发送,该类包含mortgage_rollnomortgage_name字段名,如下所示:

@IBAction func btnInsertClicked(sender: AnyObject) {
var mortgage_data: Mortgage_data = Mortgage_data()
Mortgage_data.mortgage_rollno = tmp_ Mortgage_data.mortgage_rollno.text
Mortgage_data.studentName = Mortgage_data.mortgage_name.text
var Mortgage_insert = ModelManager.instance.MortgageData(Mortgage)
if Mortgage_insert {
Util.invokeAlertMethod("", MortgageBody: " Data Inserted ", delegate: nil)
        } else {
Util.invokeAlertMethod("", MortgageBody: "Error in inserting data", delegate: nil)
        }

    Mortgage_data.tmp_rollno.text = ""
    Mortgage_data.tmp_name.text = ""
    Mortgage_data.tmp_rollno =.becomeFirstResponder()
}

FMDB 在互联网上得到了很好的文档记录并且很受欢迎。接下来,实际的 SQL 查询通过executeUpdate方法传递,这是FMDatabase类的一部分,并作为参数链接起来,作为参数的一部分:

func Mortgage_Updatedata(Mortage_data: Mortgage_Data) -> Bool {
    ModelManager.instance.database!.open()
    let Mortgage_Info_Updated {
 = sharedInstance.database!.executeUpdate("UPDATE Mortgage_data SET Mortgage_name=? WHERE Mortgage_rollno=?",withArgumentsInArray: [Mortgage_data.Name, Mortgage_data.rollno])
Mortgageinstance.database!.close()
return Mortgage_Info_Updated
}

以下代码展示了如何使用btnUpdateClicked函数以及相关字段和文本信息调用@IBAction函数,以根据名为btnUpdateClicked的按钮点击执行更新操作:

@IBActionfuncMortgage_UpdateClicked(sender:AnyObject){
    var Mortgage_data:Mortgage_data=Mortgage_data()
    Mortgage_data.mortgage_rollno =tmp_mortgage_rollno.text
    Mortgage_data.mortgage_name=tmp_mortgage_name.text

    var Mortgage_Data:Mortgage_data=Mortgage_data()
    var tmp_roll_no: String ="mortgage_rollno"
    var tmp_name: String ="mortgage_name"

var Mortgage_Info_Updated = ModelManager.instance.updateStudentData(Mortgage_data)
if Mortgage_Info_Updated {
Util.invokeAlertMethod("", strBody: "Mortgage Record has been updated ", delegate: nil)
} else {
Util.invokeAlertMethod("", strBody: "Error in updating the Mortgage record", delegate: nil)
}

    Mortgage_data.tmp_rollno.text=""
    Mortgage_data.tmp_name.text=""
    Mortgage_data.tmp_rollno=.becomeFirstResponder()
}

要执行delete操作,使用DeleteMortgateData方法。首先,使用FMDatabase类作为之前使用的方式打开数据库。之后,再次使用executeUpdate方法,并通过参数传递 SQL delete查询,通过调用FMDatabase类中定义的close方法关闭数据库。此操作的详细信息如下:

func deleteStudentData(Mortgage_data:Mortgage_Data)-> Bool {
    Mortgageinstance.database!.open()
let Mortgage_isDeleted_var= Mortgageinstance.database!.executeUpdate("DELETE FROM Mortgage_data WHERE Mortgage_data_rollno=?",withArgumentsInArray:[Mortgagedata.name])
sharedInstance.database!.close()
return Mortgage_isDeleted
}

如前所述,使用相同的ModelManager方法进行 SQL 操作:

@IBAction func btnDeleteClicked(sender:AnyObject){
var Mortgage_data:Mortgage_data=Mortgage_data()
    Mortgage_data.mortgage_rollno =tmp_mortgage_rollno.text
Mortgage_data.mortgage_name=tmp_mortgage_name.text

var isDeleted_var=ModelManager.instance.deleteStudentData(studentInfo)
if isDeleted_var{
Util.invokeAlertMethod("",strBody:"Record Deleted", delegate: nil)
}else{
Util.invokeAlertMethod("",strBody:"Error- On Deleting Record", delegate: nil)
}
    Mortgage_data.tmp_rollno.text=""
    Mortgage_data.tmp_name.text=""
    Mortgage_data.tmp_rollno=.becomeFirstResponder()
}

下一个操作是SelectMortgageData操作,它将被添加到ModelManager方法中。这将使用FMDatabase类中的open方法打开数据库。然后是使用FMDatabase类的executeQuery方法,它接受输入的 SQL 查询:

func SelectMortgageData (){
    Mortgageinstance.database!.open()
var mortgage_resultSet:FMResultSet!= Mortgageinstance.database!.executeQuery("SELECT * FROM Mortgage_data",withArgumentsInArray: nil)
        var tmp_roll_no: String ="mortgage_rollno"
        var tmp_name: String ="mortgage_name"
if resultSet{
while mortgage_resultSet.next(){
    println("roll no data is : \(mortgage_resultSet.stringForColumn(tmp_roll_no))")
    println("name data is : \(mortgage_resultSet.stringForColumn(tmp_name))"
}
}Mortgageinstance.database!.close()
}

以下方法是从上一个动作中调用的:

@IBAction func btnDisplayRecordClicked(sender:AnyObject){
    ModelManager.instance.MortgageData()
    }

使用 Firefox 查看 SQLite 方案,如图所示。打开 Firefox,在工具菜单下,调用SQLite Manager。点击Mortgage Manager表,您可以看到表的结构,如图所示:

使用 FMDB

使用 FMDB 的另一种方法是直接在 Swift 编程语言中使用,如下面的代码所示。在设置 Xcode 与 Swift 时,您将被提示输入桥接组件以将它们链接起来,但可以按照以下描述完成。

代码被添加到设置IBAction的地方。这个方法将需要使用SaveMortgageData动作方法,该方法将打开数据库,从数据字段中获取文本/信息,构建一个 SQL 数据库,并执行语句。一旦操作完成,数据库将被关闭。然后文本字段将被初始化,准备接收下一个输入。因此,使用默认模板的IBAction方法需要按照以下方式修改:

@IBAction func SaveMortgageData(sender: AnyObject) {
let Mortgage_data_save = FMDatabase(path: Database_path as String)

if Mortgage_data_save.open() {

let insertdata = "INSERT INTO Mortgage_data (mortgage_rollno, mortgage_name) VALUES ('\(tmp_mortgage_rollno.text)', '\(tmp_mortgage_name.text)')"

let mortgage_result = Mortgage_data_save.executeUpdate(insertdata, 
            withArgumentsInArray: nil)

        if !mortgage_result {
Msg_info.text = "Error inserting Mortgage Details"
println("Error: \(Mortgage_data_save.Mortgage_ErrorMessage())")
        } else {
Msg_info.text = "Mortgage Details inserted to system"
tmp_mortgage_rollno.text = ""
tmp_mortgage_name.text = ""}
    } else {
println("Error: \(Mortgage_data_save.Mortgage_ErrorMessage())")
    }
}

在使用此创建过程和方法创建了一个使用 Swift 和 SQLite 的应用程序之后,您可以看到基本组件和SQLite 3库已成功添加到新项目中。

摘要

在本章中,您快速了解了 Xcode 如何与 Swift 协同工作。本章向您展示了一些示例和想法,并介绍了应用开发环境 Xcode。我们使用了 FMDB 类和方法来访问数据库并执行各种命令。这里有一些关于 Swift 如何与 iOS 协同工作的基本但直观的示例。苹果公司编写这门语言是为了成为未来 20 年内所有开发者的下一个发展飞跃。它也已经成为开源语言。

在下一章中,您将了解到如何使用 Xcode 与 PhoneGap 和 HTML5 协同工作,以及 SQL 语句在 HTML5 中的使用,通过 PhoneGap 编译,并作为应用运行。

第七章:使用 PhoneGap 和 HTML5 进行 iOS 开发

当 PhoneGap 首次推出时,苹果公司拒绝接受由 PhoneGap 创建的应用程序作为真正的原生应用,因为它们不是原生的,而是被解释执行的。但这种情况已经改变,部分原因是因为有如此多的替代方案,部分原因是因为他们失去了数百或数千个应用程序给竞争对手,还有部分原因是因为与过去相比,开发过程本身更加简单。这些都是推动这一变化的力量。

当使用 HTML5 和 PhoneGap 编写代码时,您可以将它部署到特定的目标或平台,如 iOS 或 Android,或者默认创建多个版本,用于苹果应用商店或安卓商店等。这是使用单一代码库、较新且更容易的语言(如 HTML5)以及跨平台开发工具(如 PhoneGap)的好处。

在本章中,我们将探讨如何使用 Xcode 与 PhoneGap 集成和编译源代码,包括 HTML5。我们将向您展示如何使用 SQLite 和 SQL 语句编写代码,并将代码直接输入到 HTML5 中,然后由 PhoneGap 进行预处理。我们将涵盖从开始到结束创建默认的 Apple Xcode 应用程序的所有方面,使用 SQLite 数据库进行数据存储,并使用 PhoneGap 和 HTML5 作为起点。

HTML5 和 PhoneGap 开发

由于使用 HTML5、PhoneGap 以及通常的跨平台开发工具开发移动和平板电脑应用程序更加容易,因此似乎存在一种软件偏见,有些人认为 HTML5 开发不如原生开发技术娴熟。迄今为止,已经有一些非常糟糕的原生开发,但同样也可能适用于 HTML5 或其他应用商店中的移动应用程序。

如果您想从提供外观和感觉以及展示一些功能的设计中构建原型,使用这些现代的跨平台开发工具是一个好方法,也是快速的方法。跨浏览器技术不会像原生应用那样快速或高效,正如之前提到的,它有一个声誉,即不如原生应用真实。随着移动技术的发展,HTML5 应用程序的数量有了显著增长,因为与原生应用相比,它们的设计、开发和生产速度要快得多。

对于那些认为他们可以为移动设备制作应用程序以产生与桌面相当的东西的网页开发者来说,有一些陷阱。好吧,他们是错的。任何为 iOS 构建移动应用程序的人,例如,都必须阅读他们的人类指南文档,该文档将概述如何真正考虑用户体验、设计按钮和旅程的方式,以及如何最好地构建适合 iOS 生态系统的产品。Google/Android 的检查较少,但随着他们的应用商店的增长,我相信将会有更多或不同类型的控制措施被实施。

网络开发者必须了解这些应用的目标设备的限制。实际上,包括智能手机在内的移动设备并没有桌面那样的处理能力,网络开发者必须意识到编程原则如何在这些类型的发展中应用。

尝试新的软件技术是非常棒的;如果你有一个想法,那么尝试去创造、测试它,并将你的应用提交到 App Store。但如果你让某个人尝试创建一个原生应用,他们必须学习一门全新的语言和做事方式。直到他们能够制作出一个可工作的移动应用,这个过程可能会花费更长的时间,但到那时他们将会积累相当多的经验。有些应用采用了混合模式的原生代码,结合了跨平台开发代码,例如 HTML5。在实践中,尽管这些应用可以工作,但在性能方面存在巨大的陷阱,并且它们的局限性也很大。

构建和使用针对特定移动设备或操作系统的原生应用和应用程序有其优势,这些通常通过应用商店安装到你的手机上。这些好处包括开发速度、跨产品线的相同应用、一套代码以及应用的变更队列。理想情况下,原生是编码的最佳方式,但如果你有网络技能,不想学习新的编程语言,并且想创建一个 HTML5 应用,使用在 iOS、Android 或 Windows 上提供的 PhoneGap 可能是一个使用你技能的替代方式。

随着 HTML5 和 PhoneGap API 选项的进步,有许多新的功能,包括相机操作等,这些可以通过一些基本命令来完成。有了好的设计师,使用 HTML5 可以快速且经济地制作出相当不错的应用。

移动开发者需要接受教育,了解性能交付成果以构建应用,这些是他们可以反复使用的技能。这些好处将应用于他们生产的所有应用。

移动应用的优势超过了移动网站的直接使用。以下列出了一些优势:

  • 可以使用多种编程语言来交付最终应用,例如 Swift、Objective-C(iOS)、Java(Android)或 C#(Windows Phone)。

  • 所有“控件”和 API 在设计和发展上都是原生的,并且由苹果、谷歌或 Windows 的应用商店进行询问和批准。

  • 使用原生的另一个好处是,它不依赖于任何外部技术来工作,如果需要,还有离线工作的可能性。

根据定义,移动 Web 应用将无法访问设备和系统的底层功能。由于 API 和 HTML5、CSS 或 JavaScript 等高级语言的增强开发,这种情况正在通过软件更新和升级而改变。通过使用移动 Web/应用解决方案为移动站点,不需要应用商店的批准,并通过确保适当的代码设计,同一个应用可以在各种设备和设备尺寸以及不同的移动或桌面操作系统或浏览器上运行。信息被提供给应用,并且没有离线功能,与原生应用不同。

HTML5 因其易于使用而受到赞誉,与原生代码提供的原生设施相比。

HTML5 框架

功能,如内存分配和利用、动画以及各种其他选项,将定义一个好的 HTML5 框架是什么。这个框架确实提供了对手机设备(如摄像头或一些其他只有原生应用才能访问的内部信息)的良好访问。这些因素在很大程度上决定了要使用的框架类型。

只是因为某些框架或 JavaScript 库在一个领域很受欢迎,并不意味着它们在另一个领域就不需要。例如,jQuery JavaScript 框架因其被许多程序员在过去的大型或小型项目中使用而非常流行。

当应用运行时,最终用户很难区分原生和 HTML5 开发。然而,安装方式将决定它是一个 Web 应用还是原生应用。虽然对最终用户来说这并不重要,但用户期望有一个出色的外观和感觉、技术丰富性、易于快速导航,以及应用实际上解决了他们的问题,这是应用的首要功能。

混合应用

关于混合 HTML5 应用的使用存在一些误解。用户认为混合应用无法在 SQLite 等数据库中存储离线数据。混合应用可以在在线和离线状态下工作。它们不需要始终连接才能工作。带有 HTML5 的 PhoneGap 提供了更多的设施、功能和选项。

HTML5 应用的标准存储机制是设备本地的本地存储,即使用的数据库是 SQLite。如果你没有连接到网络,数据可以本地存储。一旦数据库连接,它将从本地数据库上传数据。

一种常见的观点是,HTML5 在原生方面并不占优势。然而,今天,通过 HTML5 可以访问应用内购买、游戏中心、执行后台任务、访问 GPS 和摄像头,甚至蓝牙。当需要为 HTML5 应用提供原生包装时,会使用 PhoneGap。原生和混合/跨平台开发应用的工作方式有一些不同,比如与 Objective-C 相比。混合/HTML5 应用运行较慢,尽管 HTML5 的功能有所增加,但仍然无法与原生相媲美。

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

在我们开始做任何事情之前,你必须首先构建环境和软件工具,并对一些小配置进行一些小的调整,以便一切准备就绪。应用程序本身将是简单的,概述了为 PhoneGap 和 HTML5 创建应用程序的过程。

你需要下载 Xcode 软件,以便使项目工作。

对于苹果用户,可以从以下位置下载 Xcode 命令行工具和 Apache Cordova 产品:itunes.apple.com/us/app/xcode/id497799835?mt=12

要获取 Xcode 和其他组件的命令行工具,请从 developer.apple.com/downloads/index.action 下载。你需要注册为苹果开发者,才能下载任何额外的组件。对于 PhoneGap 的第二种方法更简单,只需从网站下载软件并安装它,而不是使用较旧的命令行方式。

以下截图显示了 iTunes Store 中的 Xcode:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

下一个截图显示了通过 Apple 开发者账户登录时开发者可用的软件。只需要命令行 Xcode 工具。它还展示了可以下载和安装的命令行工具:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

下一个步骤是下载软件的 Cordova 模块,如下一个截图所示。这是最新 Apache/Cordova 版本的存放位置。PhoneGap 在 2011 年被 Adobe 收购,该项目本身被捐赠给了 Apache 软件基金会ASF)。使用 PhoneGap 有两种方式。一种是通过其基于云的服务来构建应用程序,另一种是通过 PhoneGap CLI 方式本地/手动构建和打包应用程序。在我们的第一个设置中,我们将使用 PhoneGap CLI 方式,如下所示:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

将 Cordova 软件下载到 下载 文件夹,解压它,然后在 cordova-ios 目录中,你可以找到使用 PhoneGap/Cordova 与 Xcode 创建简单应用程序所需的所有必要组件。以下截图显示了 Cordova/PhoneGap 系统的目录结构。正如你所见,PhoneGap 支持各种技术和跨平台:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

要继续,我们需要调用 终端 应用程序。最初,在你的 OS X 机器上,点击 应用程序 | 实用工具,然后点击 终端 应用程序,如下图所示:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

一旦点击图片,就可以看到终端应用程序的以下窗口。它将允许你继续设置环境和所需组件的过程。这是你可以执行安装所需命令的地方:

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

点击屏幕底部的工具栏上的应用程序图标,然后点击实用工具文件夹,接着点击终端图标,如下面的截图所示:

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

在选择应用程序图标后,点击实用工具文件夹:

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

一旦点击了终端窗口,将显示以下窗口:

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

一旦你进入这个目录,执行以下命令:第一个是创建一个项目,第二个是创建一个以你的应用名称命名的目录:

$cd ~/Documents
$cordova create hello com.example.helloHelloWorld

使用 Cordova 已经创建了一个Hello程序的包。在开始构建任何项目之前,系统需要知道要针对哪些平台,例如,Android、iOS 或 Windows。Cordova 现在已添加 iOS 平台,如下面的代码所示:

$ cd hello
$ cordova platform add ios

一旦添加了平台,执行以下命令将列出应用程序可以工作的平台:

$ cordova platforms ls
Installed platforms: ios 3.7.0
Available platforms: amazon-fireos, android, blackberry10, browser, firefoxos

Hello应用程序中,使用ls-l进行目录列表,你会看到各种目录,例如platforms。将platforms目录设置为默认目录。然后执行ls-l列表,你会看到包括HelloWorld.xcodeproj文件在内的各种目录。

一旦打开Hello.xcodeproj文件,Xcode 将唤醒,你会看到项目名称。你还可以输入一个公司标识符。请参见以下截图。

执行时,将提示选择一个模拟器手机。选择iPhone 6.0 的 iOS 模拟器。接下来,选择模拟器并点击运行按钮来编译、链接、构建和执行简单应用程序。你将看到 Cordova 的图像,如下面的截图所示,然后Hello应用将被显示出来:

包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

在这个阶段,你已经使用 Cordova 或 PhoneGap 设置了一个 Xcode 项目并编写了一些基本代码。现在,是时候添加一些 HTML5 代码来展示 PhoneGap/iOS 和 SQLite 如何协同工作了。

除了之前使用的安装 Cordova 的方法之外,最简单的方法是直接下载并安装 PhoneGap,而不需要通过命令行方法。点击phonegap.com/download下载页面的下载按钮。

该过程可能因某些版本而有所不同,但通常对大多数版本来说都是相同的。接下来,下载 .zip 文件,打开它并将文件提取到目录中。然后安装 PhoneGap 程序,这将提供界面,一旦这一步完成,创建一个 Xcode 项目,如下面的截图所示。由于你已经这样做过,这样做会更简单:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

当你完成了前面的任务,就像之前的安装一样,PhoneGap 将会多出一个图标。由于你已经安装了 Xcode 和 PhoneGap 共同工作所需的组件,你现在可以开始开发了。

以下截图显示了如何选择 PhoneGap 应用类型:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

在创建 Cordova 应用程序时,你必须选择基于 Cordova 的应用程序模板,如下面的截图所示:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

接下来,为这个项目选择一个项目名称——输入 Hello

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

下一个字段是用于公司标识符 ID 的。就像之前一样,请添加一个唯一的标识符,这通常是域名反转。

这是在 Xcode 中安装 PhoneGap 框架的标准方式。在你的浏览器中,访问 nodejs.org/ 并点击 安装 按钮下载名为 node.js 的 JavaScript 库。最后,输入管理员/用户名和密码详细信息以本地安装软件:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

你成功的安装信息如下:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

安装完成后,按照以下步骤操作:

  1. 打开一个终端应用程序,并输入以下命令:

    $   sudo npm install –g phonegap
    
    
  2. 输入 root 的密码以执行实际安装。一旦完成,你就可以使用 PhoneGap 命令并提示它获取一些帮助或协助。

  3. 以下截图显示了使用前面的命令安装软件的 PhoneGap 程序:

  4. 接下来,为了实际设置你的应用程序,请在终端应用程序程序中定位并设置默认目录。

  5. 运行 $ phonegap create Hello 命令。(Hello 是你的应用名称。)接下来,将默认设置为你刚刚创建的 PhoneGap 应用的应用程序目录。

以下截图显示了本地目录和创建名为 Hello 的新 Cordova 项目。一个新项目已经创建,包含了这个新测试应用所需的所有组件:

一个包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

接下来,在提示符下,执行以下命令以在 iOS 中运行应用程序。运行 $ phonegap run ios 命令。如果您从任何地方运行 iOS 项目,将显示以下错误。但如果您将默认目录设置为正确的目录(Hello),则它将工作:

带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

  1. 在下一段代码中,你可以看到调用 PhoneGap 以使应用程序工作。这个过程已经变得更加顺畅,以便操作和工作,以利于创建应用程序。

  2. 接下来,我们将向源代码中添加一些 HTML5 代码:带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

  3. 一旦新的 Hello 基本应用程序编译和构建完成,就会出现以下图像,显示 Cordova 系统。这一点非常重要,关键是要知道 PhoneGap 及其 Cordova 组件已注册并按预期工作:带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

  4. 我们现在可以通过添加一些 SQLite 和 HTML5 代码来进一步开发此应用程序。将产品的基础设置好、测试好并准备好进一步开发非常重要:带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

注意

更多关于 PhoneGap 的信息可以在docs.phonegap.com找到。

要使用 Xcode 项目文件(Hello World.xcodeproj)打开代码库,请按照以下步骤操作:

  1. 单击Hello 目录 | 平台 | iOS中的文件,这将打开 Xcode、代码和源文件。

  2. 以下是我们测试应用程序的 Xcode 源文件区域的截图。为了将 SQLite 库添加到您的项目中,请单击构建阶段选项卡,然后选择链接二进制与库菜单选项,并从libsqlite3.dyliblibsqlite3.0.dylib中选择以下库之一:带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

接下来,打开以下截图所示的HelloXcode 项目文件。在结构中,展开 Xcode 项目以显示其中的 HTML 文件。然后,将以下 HTML5 代码添加到.html文件中,编译并运行它:

带有 PhoneGap、HTML5 和 Swift 的 Xcode 项目

添加以下 HTML5 代码,它将执行一些简单的 SQLite 语句。它将接受几个输入数字;检查本地数据库/本地表的存在,创建必要的表,存储数据,并检索它。此代码将成为 Xcode 的一部分;使用 Cordova/PhoneGap 编译源代码,并执行结果以运行移动应用程序。一旦你将代码输入到Hello应用程序中的index.html文件,保存文件,并退出 Xcode。

这是一个简单的 HTML5 应用程序,它创建了一个名为testdb的数据库。它检查BLOGS表是否已创建。如果没有,它将创建BLOGS表,为博客信息输入两个记录,并在屏幕上显示数据。你可以看到以下代码和结果:

<!DOCTYPE HTML>
<html>

<head>

<script type="text/javascript">

var db = openDatabase('testdb', '1.0', 'Test DB', 2 * 1024 * 1024);
var msg;

            db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS BLOGS (id unique, log)');
tx.executeSql('INSERT INTO BLOGS (id, log) VALUES (1, "This is test blog 1")');
tx.executeSql('INSERT INTO BLOGS (id, log) VALUES (2, "This is test blog 2")');
                           msg = '<p>Blog message created and row inserted.</p>';
document.querySelector('#status').innerHTML =  msg;
                           });

                           db.transaction(function (tx) {
tx.executeSql('SELECT * FROM BLOGS', [], function (tx, results) {
var len = results.rows.length, i;
                                                        msg = "<p>Found rows: " + len + "</p>";
document.querySelector('#status').innerHTML +=  msg;

for (i = 0; i < len; i++){
                                                        msg = "<p><b>" + results.rows.item(i).log + "</b></p>";
document.querySelector('#status').innerHTML +=  msg;
                                                        }
                                                        }, null);
                                          });

</script>

</head>

<body>
<div id="status" name="status">Status Message</div>
</body>

</html>
  1. 点击终端应用程序,并在终端应用程序中,将默认目录设置为Hello应用程序目录,如下面的代码所示:包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

  2. 执行phonegap run ios命令,这将显示 PhoneGap/Cordova 启动屏幕,如下面的截图所示。这表明 Cordova/PhoneGap 环境已正确设置,应用程序将开始执行:包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

  3. 以下是从Hello应用程序输出的内容。它显示了两个插入并显示的记录。这是一个简单的过程,但工作流程与我们讨论的是相同的:包含 PhoneGap、HTML5 和 Swift 的 Xcode 项目

经过这次练习,你已经学会了如何安装 Node.js 和 Cordova,以及如何创建一个简单的 iOS 应用程序,运行 Xcode,并使用 iPhone 6 模拟一个简单的应用程序。

摘要

在本章中,你学习了如何使用 Xcode 和 PhoneGap 与 SQLite 和 HTML5。希望这已经帮助你使用这些技术进行 iOS 开发,并展示了如何使用 PhoneGap/SQLite 可以加快应用程序交付给最终用户的速度。

它也是一个跨平台开发平台,源代码只需创建一次,通过快速格式生成方法即可快速分发到各种平台。HTML5 与 Xcode、Swift 和 PhoneGap 以协同和快速的方式工作。

在下一章中,我们将讨论未来的进步、更多功能和 SQLite 功能。这将在开发过程中非常有用,以获得更好和更受控的应用程序。使用单一代码库为多个平台带来的好处对开发者和客户都非常有益。下一章还将提供如何在未来使用这些功能在新和更新的应用程序中的辅助和指南。

第八章。SQLite 的更多特性和进展

本章将探讨 SQLite 的一些新特性,并介绍该数据库的最新进展。本章将展示 SQLite 如何暴露给其他语言和框架,并讨论 C API 的扩展、PhoneGap 的使用以及其他跨平台开发环境。本章还将概述 SQLite 的其他特性以及 SQLite 如何发展以确保所有使用它的人都能快速掌握它。

您还将了解 SQLite 在近年来的变化,它如何与各种现有技术集成,以及其简单、易用的公式如何保证其在其他领域的流行。使用数据库技术的应用程序数量令人难以置信,而这些应用程序没有公开后端或本地数据库。如后文所示,SQLite 已经发展到新的水平,保持了其简单性,但同时也被开发者推向了新的高度和流行度。

Firefox 和 SQLite 扩展可用于浏览器管理目的。SQLite 已经经历了几次代码变更,未来它将继续如此发展,或者被更新的技术所取代。

Adobe 的企业管理系统与使用 SQLite 的 PhoneGap 兼容。由于其简单的设置,有多个案例展示了 SQLite 与不同技术的结合,并且整合良好。

到目前为止,关系型数据库管理系统的发展非常强劲,如果数据需要工业级的存储、应用,SQLite 是正确的格式。然而,在最近几年,如 NOSQL 这样的解决方案,它们完全依赖于从 REST API 或网络服务等技术中选择的数据,并没有使用 RDBMS(关系数据库管理系统)来存储它们的数据。数据将被检索并保存在文件类型结构中,实际上是其自己的 RDMS 版本。SQLite 没有像 数据库备份数据库恢复 这样的工业级工具支持。在一个移动设备增长迅速、超越所有类型预期的世界里,SQLite 是迄今为止使用最简单、最快的一个,学习时间最少。

Firefox SQLite 管理器功能是浏览器的良好软件扩展。一旦安装,它可以作为数据库管理员各种过程的辅助工具。

它的简单性和灵活性使其非常适合开发和测试。没有机制来确保性能,但可以调整库。SQLite 对于某些固定、单用户、移动用户和游戏信息存储的嵌入式应用来说非常出色。

SQLite 的下载和安装非常简单。一旦完成,它就会启动并开始工作。

PhoneGap 插件

在开始使用 SQLite 为 PhoneGap 开发软件之前,必须正确设置环境,以便 PhoneGap 框架能够正确地与 SQLite 一起工作。PhoneGap 环境将使 SQLite 数据库能够设置并连接到 Xcode,最终生成 iOS 应用程序。

此外,还有一个名为Brodysoft(参考build.phonegap.com/plugins/2368)的本地 SQLite 插件,它提供了一个用于存储和使用的标准 Web SQL 数据库标准的接口。

随着对移动技术、移动应用程序和移动开发的不断增长,对进一步发展的需求,例如使用 PhoneGap 等产品,将要求以下内容:

  • PhoneGap 将提高应用程序的大小限制

  • 它将支持不同的插件,包括 Cordova 插件仓库plugins.cordova.io

  • 一些额外的 PhoneGap 插件可能不需要经过审批流程,并且可以轻松获得批准

  • 将提供一个上传您自己的插件到您自己的开发区域的功能,以便您可以私下测试它们

为了支持超过 600 个在 PhoneGap 环境中的额外插件,可以使用source属性。

PhoneGap 插件,与之前不同,可以包含编译后的组件,例如框架、.jar文件和其他相关二进制文件。关于这个过程的文档在 PhoneGap 网站上有很多。PhoneGap 现在正在推进一个Amazon Mobile Ad Network插件,这将允许开发者将应用程序货币化。这是因为Amazon Ads API 已被创建用于在应用程序内进行广告,并且是一个仅为此目的的平台。它将跨不同的平板电脑、移动设备、不同的实用程序和游戏应用程序使用。

Cordova或 PhoneGap 使用的cordova.xml文件是主要参数文件,其中配置更改应用于环境。

例如,使用本地的 Cordova/PhoneGap 插件为 Android 和 iOS,可以直接使用 HTML5 Web SQL API 进行编码,如下所示。在这里,代码正在等待 API 加载完成后再尝试打开数据库:

<gap:plugin name="com.phonegap.plugins.example" version="0.3.3" source="plugins.cordova.io" />

// Wait for Cordova html5 plugin to load document.addEventListener("deviceready", onDeviceReady, false); var db; function onDeviceReady() {   db1 = window.sqlitePlugin.openDatabase({name: "DB"}); }

注意

有一个为 PhoneGap 系统开发并提供的插件github.com/litehelpers/Cordova-sqlite-storage。为了使用此插件,请将以下代码添加到您的config.xml文件中:

 <gap:plugin name="com.millerjames01.sqlite-plugin" version="1.0.1"/>

此插件与 iOS 和 Android 操作系统兼容,并且也支持 Cordova。

以下代码片段对于确保进行设备是否就绪以及 Cordova 是否就绪加载的检查至关重要:

// Wait for Cordova to load document.addEventListener("deviceready", onDeviceReady, false);
// Cordova is ready function onDeviceReady()
{   var db = window.sqlitePlugin.openDatabase({name: "DB"
}

);   // ... }

使用前面的插件,它使得将 SQL 直接包含到 HTML5 中变得更容易、更快,如下所示:

Db.transaction(function(Tx1) {
  Tx1.executeSql("Create table if not exists" + " test(id integer primary key asc, newcolumn text, []);
});
}

添加必要的 HTML 内容变得容易,并且这适用于 iOS 和 Android。HTML5、SQLite 和 PhoneGap 之间的编译关系是技术进步的体现。

并非ALTER TABLE语句的所有方面都在 SQLite 中实现,并且没有对GRANTREVOKE语句的支持。

C API 的扩展

SQLite 绑定功能扩展了 SQLite 语言的流行度和多样性,但并不受数据库核心开发者的支持。相反,SQLite 社区负责这些集成,并且在线上有很好的文档记录。脚本语言,如 Perl、PHP、Python 或 Java,与 SQLite 配合得很好。

SQLite 的 C API 接口规范有几个接口元素,可以归纳为以下几类:

  • 第一类包含 SQLite 库使用的对象和数据类型列表。其中包含十多个对象和数据类型。最有意义且最常见的是名为sqlite3的数据库对象和名为sqlite3_stmt的预处理语句。

  • 第二类将包含 SQLite 使用的常量列表,这些常量通过sqlite3.h头文件中#defines语法的使用来引用。这些是标准常量,例如SQLITE_OPEN_READONLY

  • 第三类是所有可用函数及其在对象中使用的方法列表,用于返回值和使用标准常量。

例如,int sqlite3_sleep(int);函数基于它将暂停指令执行的毫秒数。

随着移动设备的日益强大,SQLite 可以处理或使用的内存资源量总会发生变化。SQLite 内部使用的技术称为页面缓存。现在,页面缓存变得很重要,因为这是 SQLite 性能使用和设置内存的方式。它有一个 I/O 算法和两个搜索算法。有一个二分搜索使用表的索引,以及全表遍历的暴力攻击来读取整个表。由于对如何编写和实现它们的限制性决策,以及它更通用且未针对任何特定应用设计,性能通常可能不会达到预期。

尽管 SQLite 确实有一个优化器,但它不是最先进的,但它是实用的。在以下示例中,我们将看到两个表的创建和一个连接。我们将使用EXPLAIN语句,然后让 SQLite 显示它将如何获取结果。随着结果的开始显示,它将使用本节前面讨论的类别格式之一,即主要扫描。它只有在存在带有JOINSELECT语句且有索引或键的简单查询时才能正常工作。在复杂查询中,需要使用EXPLAIN语句。我们只从第一个表中选择一列,整个表进行扫描:

sqlite> CREATE TABLE one (y, z);
sqlite> CREATE TABLE two (a, b);
sqlite> EXPLAIN QUERY PLAN SELECT A FROM one JOIN two ON one.z = two.b WHERE y = 30;

0|0|TABLE one
1|1|TABLE two

在页面缓存方面,如前所述,SQLite 使用基于页面的磁盘格式。缓存与 SQLite 一起从磁盘中拉取。没有自动回收页面;一旦页面为空,就可以重用。此外,如果一个页面被反复重用,它将变得碎片化,其数据将在数据库文件中分散,这将在性能方面降低。

如本书之前所述,有来自苹果的 Core Data,这是 iOS 的标准,但免费的 SQLite 是移动设备上占主导地位且跨平台的数据库解决方案。

随着新框架的发展,出现了一种新技术,旨在取代 SQLite 和 Core Data:它被称为 Realm。它对 iOS 和 Android 都是免费的,并且是一个值得调查的好产品。虽然其他产品可能有限制,但这款产品必须确保它易于设置、使用和管理。到目前为止,它已被各种大型电子商务和数据网站使用,例如 Pinterest 或 BBC。Realm.io 是这款数据库软件的位置,是适应今天多变市场的现代 API。

在 Realm 中,有一个针对 Xcode 的插件,看起来在演示中钩入并运行良好。有一个完整的 API 参考文档,它与 Objective-C、Swift 和 Java 一起工作。Realm 还有一个来自苹果应用商店的自己的 Realm 浏览器,它被用作管理数据库的应用程序,例如 SQLite 的 Firefox 插件。

SQLite 的预写日志

Write Ahead Logging(预写日志)与 SQLite,也称为 WAL,是 SQLite 实现该移动数据库系统中 rollbackcommit 流程的标准方法。磁盘访问以及输入输出操作更加顺序化,使用的是 WAL 方法。使用 WAL 将会减少 fsync() 函数和操作的使用。这意味着它在不同的操作系统和智能手机上更有可能正常工作。WAL 在大多数操作上更快,并且提供了更好的并发性,因为没有冲突会发生在同时进行读写操作的过程中,任何数据块都将大幅减少。

尽管这种方法有很多优点,但也有局限性。WAL 在处理非常大的事务时效率不高,但处理较小的事务时则要好得多。对于大约 100 兆字节的事务,它将运行良好,但超过 1 吉字节,它将开始降低其效率。还有一个问题:如果 WAL 遇到 磁盘满 错误,它可能会失败操作,尽管,一个额外的操作是 检查点,它是作为系统的一部分嵌入的。开发者需要意识到这一点。

WALrollback 可能比当前/传统的方法操作要慢。这是因为数据库的读取量和低写入尝试量。这仅限于 1-2% 的范围内。另一个缺点是,在使用 WAL 模式时,即使数据库为空,也无法更改数据库页面大小。为了解决这个问题,你必须使用提供的 BACKUP API 从备份中恢复,并且你必须处于回滚日志模式才能成功。还有读取 只读 WAL 数据库的问题。

WAL 的工作原理是通过创建并写入一个不包含任何更改的原始数据库副本到一个新的/独立的回滚日志文件中。然后直接对数据库文件进行更改。如果发生崩溃并且系统必须执行 rollback 操作,那么未更改的原始版本将被回放到数据库文件中,使其恢复到原始状态。当删除回滚日志文件时,执行 commit 操作。这是一个非常有效的程序。向磁盘写入事务总是很快,因为内容只写入一次。

SQLite 中 B 树的使用

叶节点的任意存储及其在物理磁盘上的位置不会与索引顺序或任何逻辑位置链接或响应。因此,使用正确的结构,数据库搜索算法被用来改变位置并快速输出一个平衡搜索树,简而言之,就是一个 B 树。每个数据分支都将有其叶节点,这些叶节点将链接或引用用于存储数据库中每个表的内存位置。

B 树允许基于节点中的一般二叉搜索树进行顺序访问、删除和插入,节点可以有两个或更多子节点。当数据被移除或添加时,子节点数量会发生变化,为了保持特定的范围,一些内部节点可能会合并或分裂。B 树结构中的每个内部节点都将有一个键的数量。每个键都将有一个值,并将被分成子树。B 树是查找与键关联的数据的好方法,但它在搜索带有查询字符串的数据时效率不高;它使用索引来加速这种搜索。B 树是搜索带有键的数据的有效方法,并且当正确执行时,它们变得非常快。这是关于 B 树及其在 SQLite 中应用的解释。

创建一个简单的 Swift

随着 Swift 和 Swift2 的出现,现在有一个称为 playground 的环境被使用。这是一个你可以设置一个带有一些代码的快速环境并查看结果的地方。这是一种快速、新的使用新设置的方法。当你开始时,它将有一个主窗口和第二个,分割的结果窗口。

在 Xcode 中,导航到 新建 | Playground,以下截图将显示。给你的 playground 起一个名字。你可以在不同的平台上运行多个 playground,因此一个有意义的名字会有所帮助:

创建简单的 Swift

一旦创建完成并点击下一步按钮,就会出现以下屏幕。在这里,您可以创建代码,测试想法和代码片段,并尝试运行。这是一个既简单又伟大的想法,将有助于激励现有开发者,并为未来的开发者创造机会:

创建简单的 Swift

如前一个截图所示,右侧有一个分页,可以根据要求进行调整。代码出现在左侧,结果出现在右侧。在前面的代码中,调用了 UIKIT;下一行创建了一个名为 str 的变量,其默认字符串值为 Hello playground

UIKit 是用于应用程序开发的 iOS 框架的核心基础。将 var 定义为 str 等于 Hello Playground 以便更改后,应将其定义为 str = New Playground,这将重新分配变量为新值。使用 var 语句创建默认系统,然后分配它,表明默认变量值可以被更改。然而,如果您使用 let 语句说 let str =new play 并紧接着添加 str =newnewplay line,系统会抛出错误,因为您不能使用 let 命令更改常量的值。

演示场可以接受不同类型的数据类型,正如您所想象的,这使得它成为进入开发或测试新想法的有趣而富有成效的方式。在下一个简单的例子中,设置了一个名为 age 的变量,其数据类型为 int

给这个值赋予一个默认值 25。然后,将年龄值乘以 10,您将得到一个新的值 250,如以下截图所示。这是演示场的美丽之处:

创建简单的 Swift

Swift 拥有丰富的比较运算符,就像大多数语言一样,但您可以使用 => 方式,也可以使用 < 方式,如以下截图所示:

创建简单的 Swift

Swift 的字符串插值也更容易,通过创建一个变量然后使用命令打印名称,例如,使用 \(name)(其中 name 是变量名),如以下截图所示。这很简单,但反复练习是很好的,这样信息就能在您的脑海中固定下来:

创建简单的 Swift

如以下截图所示,在 Swift 中,+ 连接运算符的使用不起作用,尤其是字符串、双精度浮点数或整数的合并。但下一张图清楚地显示了在 nameagelatitude 之间的 \ 可以成为正确语法的部分,正确地表达输出:

创建简单的 Swift

在 Swift 中使用数组更为简便,这些数组将存储数据集合,例如网格,作为大量信息集合的一部分。一个名为 oddNumbers 的数组将包含四个数字,例如 (3, 5, 7, 9)。还有一个名为 songs 的数组,如下所示:

创建简单的 Swift

Swift 语言非常广泛,有许多示例,但我们无法在本章中涵盖所有内容。本章将向您展示 SQLite、PhoneGap 的更新以及 Swift 的一些更新。

例如,for 循环更容易使用,这在以下屏幕截图中有明确的展示。在这个语句中,打印语句将运行 10 次,如以下屏幕截图所示:

创建简单的 Swift

这里是尝试使用 for 命令的另一个例子,其中循环中的数字不是必需的,而是使用 _ 代替。但是,str 打印命令已经执行了五次,因为寻找并打印了单词 gone,如以下截图所示:

创建简单的 Swift

如前所述,使用游乐场将——正如其名所示——Swift 且有趣

只需将其粘贴到代码中,然后运行即可。从 Xcode 7 及以后版本开始,你可以放入游乐场的实际代码将是丰富的、有注释的,并且远不止伪代码,因为它可以添加到你的应用程序中。

你将能够添加丰富的文本功能、注释以及其他有助于编程过程开发和创造性的文本。

想象一下,当 API 更新发布时,这将是一种查看 API 并编写或修改一些代码以使其在游乐场中工作的极好且快速的方式。除了提供信息和快速之外,它还将作为你和你同事的培训工具。它将提高培训课程,并使开发者能够在不影响他人及其共同项目的情况下尝试新想法和编程代码。

这是一种多么美丽、互动且现代的学习和使用现有编程技能以获取新知识的方式。Swift 中交互式调试控制台的使用和可用性允许对产品进行改变/增强,从而现代化其努力。

由于它是从头开始设计的,Swift 致力于快速、行动迅速且编码迅速,并且与 Objective-C 兼容性以及 Swift 一起包括和共享库、代码和值,因为现代 21 世纪的编译器将有助于其在未来几年的主导地位。Objective-C 和 Swift 代码可以共存并协同工作或单独工作。

内置的高性能编译器是为了最大化苹果硬件、协议和网络可用性而创建的。它已优化以非常快速地运行并提高开发和编译速度。

作为其产品组合的一部分,Swift 语言是最现代的语言之一,它采用了其他脚本语言的“最佳”部分,并消除了诸如性能不佳或与语法相关的问题,从而超越了 C 和 Objective-C 代码范式。世界上有许多语言。但 Swift 是唯一一种你可以用现代方式编码和学习的语言。通过现在学习,你正在为不久的将来做准备,那时这种语言将变得流行。它是 Objective-C 和 C 相关语言的完全继任者。

Swift 被设计成现代的,并摒弃了那些实际上会阻止程序员发展的功能。因此,所有阻碍缓慢发展的因素都已消失。例如,所有值默认情况下都不是 null。语言的安全性得到了鼓励,并作为软件的一部分构建,例如,变量使用var语句,而let语句将用于常量。例如,在定义任何“Swift”对象时,值不会是 nil,因为编译器会处理它并将其作为安全制度的一部分。强制这些类型的细微之处鼓励编写更好、更专业、更干净、更有趣和更具创新性的代码。

Swift 拥有一个卓越的现代且改进的错误处理模型,它将提供一种清晰简洁的方式来使用最先进、面向对象的技术开发和获得现代技能。它还捕获任何必要的错误,以便程序不会崩溃,并处理它。它与NSError和其他相关 iOS 框架配合得很好。例如,请参见以下内容:

func UnloadData() throws { }

func zTest() {
    do {
        try UnloadData()
    } catch {
        print(error)
    }
}

Swift2 现在已被开源,这将鼓励更多不同平台上的用户进行软件的架构、设计和开发。这将使苹果能够进入市场上竞争对手经常使用的开发领域。它将拥有庞大的追随者,尤其是当那些忠诚的 Objective-C 程序员转向 Swift 时。

使用一些出色的强大语言/语法,如repeatdeferguard,可以在 Swift 中编写新颖、有趣和功能强大的代码。苹果还提供了一种迁移工具,可以将代码转换为新的游乐场和应用程序开发代码,以便轻松执行。这些是使用 Swift2 进行开发所期待的一些好处。

Swift 的设计目标是现代的,Swift2 采用了来自现代研究、编程语言以及不同苹果开发、产品和编码技能的先验经验的信息、功能以及编译器开发。一种现代的方法,以及结构扩展和协议的能力,将确保其存在一段时间。

摘要

在本章中,你学习了 SQLite 的一些高级方面和未来的进步,以及它是如何与当前跨平台开发相匹配的。本章概述了 SQLite 的变化及其增长与 PhoneGap 的联系。PhoneGap 还与内容管理系统集成,例如 Adobe Enterprise Manager,该系统在技术方面取得了几个进步,并且客户端许可证的购买激增了其知名度。在本章中,你还触及了新 Swift 语言中可能实现的内容以及它将如何影响游戏、应用程序和实用程序的未来。

posted @ 2025-09-29 10:35  绝不原创的飞龙  阅读(58)  评论(0)    收藏  举报