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

iOS关于移动端SQLite,你想知道的都有

一、SQLite简介SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目

一、SQLite简介

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。


二、SQLite优势

  • 1、占用资源低
  • 2、速度快
  • 3、与其他数据库相比,更适配移动平台、嵌入式平台


三、SQLite支持的存储类型有:

1、INTEGER - 整形
2、blob - 二进制
3、real - 浮点型
4、text - 字符串
5、NULL - 空


注意:在SQLite中大小写不区分,也就是AA = aA = Aa = aa


四、SQLite学习之DDL

DDL(Data Definition Language):数据定义语言,用来创建数据库中的各种对象—–表、视图、
索引、同义词、聚簇等

  • 创建表

CREATE TABLE 表名 (字段名 字段类型,字段名1 字段类型1,...);

  • 删除表

DROP TABLE 表名;


DDL – 创建表:




CREATE TABLE T_Person(id INTEGER, name TEXT,age INTEGER);
在这里我们通常有两种书写格式,假设语句不是很长的情况下,
可以写成一行,但是如果语句过长就不利于阅读,所以有了下面的格式:
CREATE TABLE T_Person
(
id INTEGER,
name TEXT,
age INTEGER
);

通过上述代码我们就可以创建一个表了,但是如果在执行一次上面的语句, 就会发现报错了,
错误:文件已存在Error : table T_Person already exists
所以我们创建的时候需要判断表是不是存在
于是有了下面的创建语句:

CREATE TABLE IF NOT EXISTS T_Person
(
id INTEGER,
name TEXT,
age INTEGER
);

其中

IF NOT EXISTS : 如果不存在
上面创建的语句翻译就是:
创建一个表,如果不存在的话就创建


DDL – 删除表:

DROP TABLE T_Person;


五、SQLite学习之DML

DML(Data Manipulation Language)数据库操作语句:
关键字有insert,update,delete
分别对应:插入、更新、删除

  • 插入数据

INSERT INTO 表名(字段...) VALUES(值...);

  • 更新数据

UPDATE 表名 SET 字段名=值,...;

  • 删除数据

DELETE FROM 表名;


DML – 插入数据:

INSERT INTO T_Person1 (name,age) VALUES('zs',20);
在现实生活中我们可能会遇到这样一种情况:
在一个班里,有可能有两个人的姓名完全一致,这个时候我们
就需要进行区分,就像每个人都有一个身份证号,且唯一

《iOS - 关于移动端SQLite,你想知道的都有》 这个时候如何区分?


如果想保证数据唯一:

这个时候就需要主键:PRIMARY KEY,所以我们要修改我们的创建表的语句
修饰主键的方法有两种:

  • 方法一:

CREATE TABLE T_Person
(
id INTEGER PRIMARY KEY,
name TEXT,
age INTEGER
);

  • 方法二:

CREATE TABLE IF NOT EXISTS T_Person1
(
id INTEGER,
name TEXT,
age INTEGER,
PRIMARY KEY (id)
);



这个时候我们再次执行插入语句

INSERT INTO
T_Person1 (id,name,age)
VALUES(1,'zs',20);
.
第一次:Affected rows : 1, Time: 0.00sec
第二次:Error : UNIQUE constraint failed: T_Person1.id

从上面的结果可以看出,id不能相同,那怎么样才能保证ID不相同,
又不输入id这个属性呢?因为人输入,可能会存在差错,交给机器做最好。
于是我们要用到个新的关键字:AUTOINCREMENT 自增
所以我们还要在修改一次创建语句:

CREATE TABLE IF NOT EXISTS T_Person1
(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
age INTEGER
);



现在我们就可以肆无忌惮的执行下面这条插入语句了

INSERT INTO
T_Person1 (name,age)
VALUES('zs',20);



下面是执行了5次的之后的表:

《iOS - 关于移动端SQLite,你想知道的都有》 执行了5次之后

现在我们完全可以不用管理ID这个字段,并且现在每一条数据都是唯一的。



但是在某些情况下还是会有不完善的地方,比如下面这条插入语句:

INSERT INTO
T_Person1 (age)
VALUES(35);



然后我们来查看一下表:

《iOS - 关于移动端SQLite,你想知道的都有》 插入了一条姓名为空、年龄是35的数据

这样子看似乎没有问题,但是结合实际情况来看,假设这是一个班级的数据,我不希望我的学生连名字都没有,这个不像话。

然后没错,又要使用一个新的关键字:NOT NULL 不为空

然后再次更新表的创建语句:

CREATE TABLE T_Person1 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER
);

然后我们再次执行上面的语句

INSERT INTO
T_Person1 (age)
VALUES(35);
错误提示:Error : NOT NULL constraint failed: T_Person1.name

这个时候就会报错:提示我们名字不能为空



于是我们要写成:

INSERT INTO
T_Person1 (name,age)
VALUES('xiaoming',35);
提示:Affected rows : 1, Time: 0.00sec



再次查看表:

《iOS - 关于移动端SQLite,你想知道的都有》 插入数据

然后我们在介绍一个属性:DEFAULT 默认值
使用方法就是在字段名后面

age INTEGER DEFAULT 15
表示定义了一个age 字段 默认是15



这个时候我们的创建表语句如下:

CREATE TABLE T_Person1 (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER DEFAULT 15
);



然后我们插入数据:

INSERT INTO T_Person1 (name) VALUES('zs');
INSERT INTO T_Person1 (name,age) VALUES('ls',18);
INSERT INTO T_Person1 (name,age) VALUES('zs',25);
INSERT INTO T_Person1 (name) VALUES('zl');



表如下:

《iOS - 关于移动端SQLite,你想知道的都有》 数据表图

通过上面的了解我们就知道如何插入数据,并且设置字段了。


DML – 更新数据:

UPDATE T_Person1 SET name='qq';
执行这行语句后会发现所有的名字都变成了qq



更新多个字段

UPDATE T_Person1 set name='qq',age=20;



如图:

《iOS - 关于移动端SQLite,你想知道的都有》 更新数据之后

在上面的代码中我们已经完成了对数据库的更新,但是却不是我们想要的结果,上面的是对整个数据库都进行了更新,如果我们只想对某个数据更新改如何解决呢?后面会讲到


DML-删除:

DELETE FROM T_Person1;
执行完上面语句之后查看打印:
Affected rows : 4, Time: 0.00sec 影响了四行数据



然后我们再来看表

《iOS - 关于移动端SQLite,你想知道的都有》 空空如也

这个时候我们就已经完成了对DML的学习,但是这些还不够,比如我们更新数据的时候是对整个表进行更新,
删除也是把整个表进行删除,如果我们想对指定的数据进行操作,我们需要学习一个新的关键字:
WHERE 条件

WHERE

SQLite的 WHERE 子句用于指定从一个表或多个表中获取数据的条件。
如果满足给定的条件,即为真(true)时,则从表中返回特定的值。您可以使用 WHERE 子句来过滤记录,只获取需要的记录。
SQLite的运算符有四种:算数、比较、逻辑以及位运算符
算数运算符:

+ 加法 - 把运算符两边的值相加 a + b 将得到 30
- 减法 - 左操作数减去右操作数 a - b 将得到 -10
* 乘法 - 把运算符两边的值相乘 a * b 将得到 200
/ 除法 - 左操作数除以右操作数 b / a 将得到 2
% 取模 - 左操作数除以右操作数后得到的余数 b % a will give 0

比较运算符

== 检查两个操作数的值是否相等,如果相等则条件为真。 (a == b) 不为真。
= 检查两个操作数的值是否相等,如果相等则条件为真。 (a = b) 不为真。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。 (a != b) 为真。
<> 检查两个操作数的值是否相等,如果不相等则条件为真。 (a <> b) 为真。
>> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 (a > b) 不为真。
<检查左操作数的值是否小于右操作数的值,如果是则条件为真。 (a >= 检查左操作数的值是否大于等于右操作数的值,如果是则条件为真。 (a >= b) 不为真。
<= 检查左操作数的值是否小于等于右操作数的值,如果是则条件为真。 (a <= b) 为真。
!<检查左操作数的值是否不小于右操作数的值,如果是则条件为真。 (a !!> 检查左操作数的值是否不大于右操作数的值,如果是则条件为真。 (a !> b) 为真。

逻辑运算符:

AND AND 运算符允许在一个 SQL 语句的 WHERE 子句中的多个条件的存在。
BETWEEN BETWEEN 运算符用于在给定最小值和最大值范围内的一系列值中搜索值。
EXISTS EXISTS 运算符用于在满足一定条件的指定表中搜索行的存在。
IN IN 运算符用于把某个值与一系列指定列表的值进行比较。
NOT IN IN 运算符的对立面,用于把某个值与不在一系列指定列表的值进行比较。
LIKE LIKE 运算符用于把某个值与使用通配符运算符的相似值进行比较。
GLOB GLOB 运算符用于把某个值与使用通配符运算符的相似值进行比较。GLOB 与 LIKE 不同之处在于,它是大小写敏感的。
NOT NOT 运算符是所用的逻辑运算符的对立面。比如 NOT EXISTS、NOT BETWEEN、NOT IN,等等。**它是否定运算符。**
OR OR 运算符用于结合一个 SQL 语句的 WHERE 子句中的多个条件。
IS NULL NULL 运算符用于把某个值与 NULL 值进行比较。
IS IS 运算符与 = 相似。
IS NOT IS NOT 运算符与 != 相似。
|| 连接两个不同的字符串,得到一个新的字符串。
UNIQUE UNIQUE 运算符搜索指定表中的每一行,确保唯一性(无重复)。

位运算符:

& 与
| 或
p q p & q p | q
0 0 0 0
0 1 0 1
1 1 1 1
1 0 0 1



在了解了WHERE之后呢我们就可以对数据库进行指定某条删除、更新等操作了
先向数据库中 插入一些数据

INSERT INTO T_Person1 (name,age) VALUES('aa',20);
INSERT INTO T_Person1 (name,age) VALUES('bb',18);
INSERT INTO T_Person1 (name,age) VALUES('cc',24);
INSERT INTO T_Person1 (name,age) VALUES('dd',22);
INSERT INTO T_Person1 (name,age) VALUES('ee',19);
INSERT INTO T_Person1 (name,age) VALUES('ff',22);
INSERT INTO T_Person1 (name,age) VALUES('gg',19);
INSERT INTO T_Person1 (name,age) VALUES('hh',18);



然后数据表中数据如下:

《iOS - 关于移动端SQLite,你想知道的都有》 数据图

DML-更新/删除指定数据

UPDATE
T_Person1
set
name='ff',age=20
WHERE
name='bb';
表示我要更新一个姓名叫做bb的人数据,并且把他的名字设置为qq、年龄设置为20岁
Affected rows : 1, Time: 0.00sec 提示已经影响了一条数据



此时查看表如下:

《iOS - 关于移动端SQLite,你想知道的都有》 更新了之后

如果你足够细心,你就发现了现在有两个人名字都叫ff了,如果我现在只想对第一个姓名叫ff的人更新数据
我们可以这样子写:

UPDATE
T_Person1
set
name='ee',age=19
WHERE
name='ff' AND age=20;



然后表现在的数据如下:

《iOS - 关于移动端SQLite,你想知道的都有》 更新数据之后

OK,通过上面的语句我们完成了只对第一个名字叫ff的人更新数据,但是现在我想对
第二个姓名为ee进行更新,就很尴尬了,数据库中有两个姓名都叫ee的并且年龄都是19岁,
到了这里我们定义id为唯一的作用就发挥出来了,此时我们只需要更新
指定id即可

UPDATE
T_Person1
set
name='bb',age=28
WHERE
id=9;



更新之后如图:

《iOS - 关于移动端SQLite,你想知道的都有》 更新之后

OK,通过上面的代码我们就可以知道如何对指定的数据进行更新了,下面我们简单的说下删除指定数据.

DELETE FROM
T_Person1
WHERE
name='gg';



如图:

《iOS - 关于移动端SQLite,你想知道的都有》 删除之后



如果我想删除多条数据呢?
比如删除20岁以上的

DELETE FROM
T_Person1
WHERE
age>20;
Affected rows : 4, Time: 0.00sec 影响了四行,应该是删除了四行,
我们查看更新之后的表



表:

《iOS - 关于移动端SQLite,你想知道的都有》 删除之后

七、SQLite学习之DQL:

DQL(Data Query Language)数据查询语言
关键字:Select,同时也是使用频率最高的
查询数据
SELECT 字段名,&#8230; FROM 表名;



先插入一下数据进去

INSERT INTO T_Person1 (name,age) VALUES('ab',28);
INSERT INTO T_Person1 (name,age) VALUES('hg',25);
INSERT INTO T_Person1 (name,age) VALUES('ab',24);
INSERT INTO T_Person1 (name,age) VALUES('df',22);
INSERT INTO T_Person1 (name,age) VALUES('fd',23);
INSERT INTO T_Person1 (name,age) VALUES('yt',28);
INSERT INTO T_Person1 (name,age) VALUES('oi',21);
INSERT INTO T_Person1 (name,age) VALUES('qw',33);
INSERT INTO T_Person1 (name,age) VALUES('gf',19);
INSERT INTO T_Person1 (name,age) VALUES('kl',18);
INSERT INTO T_Person1 (name,age) VALUES('lj',23);
INSERT INTO T_Person1 (name,age) VALUES('rt',25);
INSERT INTO T_Person1 (name,age) VALUES('tr',28);
INSERT INTO T_Person1 (name,age) VALUES('qw',26);
INSERT INTO T_Person1 (name,age) VALUES('xx',24);
INSERT INTO T_Person1 (name,age) VALUES('zx',25);
INSERT INTO T_Person1 (name,age) VALUES('mn',24);
INSERT INTO T_Person1 (name,age) VALUES('vb',25);



然后可以看到表数据如下:

《iOS - 关于移动端SQLite,你想知道的都有》 数据表如图



OK,在填充了数据之后,我们开始查找

SELECT * FROM T_Person1;
在这里*代表通配符,所有的字段

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 查找之后

现在我们不想看到那么多数据,假设我们只显示age

SELECT age FROM T_Person1;

如图所示

《iOS - 关于移动端SQLite,你想知道的都有》 单个字段

查询多个字段: 这里字段的输入顺序就和显示的列名数据一致

SELECT age,name FROM T_Person1;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 多个字段

OK,需求总是要变来变去的,这个时候我们想查询年龄大于22岁的数据,并且显示所有的信息

SELECT * FROM T_Person1 WHERE age>22;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 条件查询



然后我们想找名字为ab的人,不要显示id

SELECT name,age FROM T_Person1 WHERE name='ab';

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 条件查询二

如果你看到了这里,那么恭喜你,你已经知道了如何创建/删除表,以及对表的增删改查,同时还了解了WHERE条件语句,到这里基本上你已经可以自己管理数据库了。


扩展知识 &#8211; 动态添加字段

继续上面的表,这个时候老师分配任务啦,给每个人100块的启动资金,然后一个月后来查看他们是让100块变成了0块还是变成了更多,这个时候上面就来话了,你给我添加一个字段进去,保存他们的金钱额度。
但是这个需求在项目开始之初是没有考虑到的,这就比较坑爹了,原来的数据库文件的内容不能删除,又要新增一个字段……愁死我了。
方法有很多种,这里不作介绍了
只是来介绍一下动态添加字段这个方法


ALTER TABLE 表名 ADD 字段名 字段类型;

未插入字段之前的表:

《iOS - 关于移动端SQLite,你想知道的都有》 未插入之前

插入一个字段:money

ALTER TABLE
T_Person1
ADD
money real DEFAULT 100.0;

《iOS - 关于移动端SQLite,你想知道的都有》 插入之后

OK,到这里完美解决了之前的问题

注意:再插入一个字段之前,讲道理我们是要看下里面有没有这个字段的

比如你正在上厕所,突然有个人就进来把你赶出去了,占了你的坑,此时的你肯定是在暴怒状态,正常的应该是:先看下里面有没有人,有人了就换一个,没人然后在进去占一个坑……
所以我们需要判断一下是不是可以插入这个字段

SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol);

通过上面的方法会返回给我们一个C字符串数组判断这个数组是不是有值,如果有了就不能插入了



为此我特地的又运行了一次

Error : duplicate column name: money
提示说有两个都叫money的列了


扩展知识 &#8211; AS(起别名)

可以暂时把表或列重命名为另一个名字,这被称为别名。使用表别名是指在一个特定的 SQLite 语句中重命名表。重命名是临时的改变,在数据库中实际的表的名称不会改变。
列别名用来为某个特定的 SQLite 语句重命名表中的列。

比如:给字段起别名

SELECT
name as xingming,
age as nianling
FROM
T_Person1
WHERE
age>25;



如图:

《iOS - 关于移动端SQLite,你想知道的都有》 字段别名

给表起别名:

SELECT
one.name as one_name,
one.age as one_age
FROM
T_Person1 as one
WHERE age>25;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 表别名

多表查询:
先创建一个T_Person2表,然后插入一下数据

CREATE TABLE IF NOT EXISTS
T_Person2(
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
age INTEGER DEFAULT 20,
money REAL DEFAULT 100.0
);
INSERT INTO T_Person2 (name,age) VALUES('asdf',28);
INSERT INTO T_Person2 (name,age) VALUES('hsdfg',25);
INSERT INTO T_Person2 (name,age) VALUES('afdfb',24);
INSERT INTO T_Person2 (name,age) VALUES('dfasdf',22);
INSERT INTO T_Person2 (name,age) VALUES('ffdfd',23);
INSERT INTO T_Person2 (name,age) VALUES('yfdft',28);
INSERT INTO T_Person2 (name,age) VALUES('ocvi',21);
INSERT INTO T_Person2 (name,age) VALUES('qwvc',33);
INSERT INTO T_Person2 (name,age) VALUES('gvcvf',19);
INSERT INTO T_Person2 (name,age) VALUES('kcvcl',18);
INSERT INTO T_Person2 (name,age) VALUES('lvj',23);
INSERT INTO T_Person2 (name,age) VALUES('rvcdst',25);
INSERT INTO T_Person2 (name,age) VALUES('tr43',28);
INSERT INTO T_Person2 (name,age) VALUES('qwgh',26);
INSERT INTO T_Person2 (name,age) VALUES('xgfdx',24);
INSERT INTO T_Person2 (name,age) VALUES('hfgzx',25);
INSERT INTO T_Person2 (name,age) VALUES('mgfhn',24);
INSERT INTO T_Person2 (name,age) VALUES('vhgb',25);

这个时候,T_Person1里面有的字段T_Person2里面也有,就想两个班级里面的字段
都有姓名,年龄等数据。
别名这个时候就可以很方便的区分

SELECT
one.name as one_name,
one.age as one_age,
two.name as two_name,
two.age as two_age
FROM
T_Person1 as one,
T_Person2 as two
WHERE
one.age>30 AND two.age>30;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 如图

写别名的方式还有一种,但是不推荐,直接加个空格

SELECT name xingming,age nianling
FROM T_Person2;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 别名


扩展知识 &#8211; 排序

ORDER BY,用于对数据进行排序
考虑这么一种情况,当你把数据信息输入进去,而数据本身是杂乱无章的,这个时候你需要排序,比如:name、age字段来排序。
DESC : 降序
ASC:升序


单个字段排序

SELECT
*
FROM
T_Person2
ORDER BY
age;

如图:根据age升序

《iOS - 关于移动端SQLite,你想知道的都有》 单个字段排序



多个字段排序

SELECT
*
FROM
T_Person2
ORDER BY
name,age;

如图:根据name升序,在根据age升序

《iOS - 关于移动端SQLite,你想知道的都有》 多个字段排序

通过上面的语句我们发现在不写明是什么排序的情况下默认是升序,也就是ASC



通过写上ASC来证明:

SELECT
*
FROM
T_Person2
ORDER BY
name ASC,age ASC;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》



下面根据age字段进行降序

SELECT
*
FROM
T_Person2
ORDER BY
age DESC;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 age降序



最后我们在实现一个根据name升序,age降序的
先别着急,因为我们数据库中没有相同姓名的,所以我们先插入两条数据
插入数据

INSERT INTO T_Person1(name,age) VALUES('aa',18);
INSERT INTO T_Person1(name,age) VALUES('aa',19);

检索

SELECT
*
FROM
T_Person1
ORDER BY
name ASC,age DESC;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 检索如图


扩展知识 &#8211; 数量

快速查询有多少条数据或者查询某个字段有多少条数据

SELECT COUNT(字段) FROM 表名;



查询有多条数据:

SELECT COUNT(*) FROM T_Person1;

如图

《iOS - 关于移动端SQLite,你想知道的都有》 检索



检索age字段条数:

SELECT COUNT(age) FROM T_Person1;

《iOS - 关于移动端SQLite,你想知道的都有》 age


扩展知识 &#8211; 分页取数据

Limit常用来对数据进行分页,比如每页固定显示n条数据

SELECT 字段... FORM 表名 LIMIT a,b;
a:表示跳过多少条数据
b:从a之后开始取多少条数据

在网络请求的时候我们经常可以向服务器说明,从哪一页开始,取多少条,类似这样子的操作很频繁。



举例:每页取10条数据

  • 第1页:&#8230; LIMIT 0,10;
  • 第2页:&#8230; LIMIT 10,10;
  • 第3页:&#8230; LIMIT 20,10;
  • &#8230;
  • 第n页:&#8230; LIMIT 10*(n-1),10;

于是我们可以得出一个公式:
m:每次取多少
n:页
m*(n-1),m


注意:LIMIT 10 = LIMIT 0,10,两个语句相等



代码:取10条数据,从0开始

SELECT * FROM T_Person1 LIMIT 10;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 limit



如果我们数据库中没有那么多的情况下,就会把剩下的全部都取出来
比如:T_Person1中我们只有23条数据,在上面检索出来过
执行:

SELECT * FROM T_Person1 LIMIT 20,10;

如图:

《iOS - 关于移动端SQLite,你想知道的都有》 limit 20,10



OK,进一步增加难度,我要取得age>20的前面10条数据

SELECT *
FROM T_Person1
WHERE age>20
LIMIT 10;

《iOS - 关于移动端SQLite,你想知道的都有》 检索age大于20的数据,取十条
《iOS - 关于移动端SQLite,你想知道的都有》



然后我们在联合排序提取数据:

SELECT *
FROM T_Person1
ORDER BY age DESC
LIMIT 10;

如图

《iOS - 关于移动端SQLite,你想知道的都有》 根据age进行排序(降序),取前面十条

对比查看数据是不是正确

《iOS - 关于移动端SQLite,你想知道的都有》 对比

通过两个图比较,发现取出来的数据确实是正确的。



文中一些比较简短的语句其实没比较分行分的那么清楚,只是笔者为了能让人阅读起来更加方便,有写笔者也没有进行分行,不过阅读起来应该还是比较简单的。
OK,如果你坚持看完了,希望或多或少能给你带来一些小小的帮助。
笔者写这个也花了一点时间,如果能让您复习或者有幸让你更了解SQLite的话,就不枉费这些时间了。

最后厚着脸皮求个喜欢,那是我最大的动力。后面会更新如何在Swift3.0的中使用。

18/07/12 联合查询

Select * from 表一 join 表二 on 关联条件 where 筛选条件
多个筛选条件中用 AND 分隔

假设有一个Person 表,设计如下:

字段名类型描述
user_idtext用户主键
nametext用户姓名

一个Action

字段名类型描述
user_idtext主键
actiontext动作

现在我们要如何知道用户执行了什么操作?使用join

select * from //查找所有字段
Person as p join Action as a //把表关联
on p.user_id=a.user_id // 关联的字段
where p.user_id = 'xxx' //筛选的条件
select p.name, a.action from //只显示 name 和 action
Person as p join Action as a //把表关联
on p.user_id=a.user_id // 关联的字段
where p.user_id = 'xxx' and a.action = 'xxxxx' //筛选的条件

推荐阅读
  • 正则表达式及其范例
    为什么80%的码农都做不了架构师?一、前言部分控制台输入的字符串,编译成java字符串之后才送进内存,比如控制台打\, ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • 下面的是我的login.jsp程序当选择复选框陌生人登录的时候,点击“登录”按钮,可以进入留言界面。当有正确的用户名跟密码登录的时候就进入留言界面。但是当我都没有选择的时候直接点击“登录”按钮也可 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
  • phpgettext.dll的简单介绍
    本文目录一览:1、在php.ini中设置了extension=php_gettext.dl ... [详细]
  • 常用DOS命令,程序员的帮手
    2019独角兽企业重金招聘Python工程师标准cleanmgr–打开磁盘清理工具compmgmt.msc---计算机管理conf— ... [详细]
author-avatar
刘莉长
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有