转载请注明出处:https://blog.csdn.net/turtlejj/article/details/105015349,谢谢~

最近在工作中,看到有一部分同事,在查看Android应用程序的数据库文件时,都要先通过adb pull命令,把db文件从手机拷贝到电脑端,再通过一些软件打开查看。这种方式虽然没有什么问题,但在执行某些操作后,数据库发生变化,如果想再次查看,又要再执行一次adb pull操作,很麻烦。

其实,我们完全可以通过adb shell,使用sqlite3这个命令行工具,来查看我们db文件中的表、表结构以及表中存储的数据。

本篇文章,既是我给自己写的一份备忘,也希望能为不熟悉sqlite3工具的同学提供一份命令速查手册,方便大家在使用的时候,不用再去各个地方查找资料。

当然,由于篇幅原因,我们这里并不会列出sqlite3的所有命令,但对于Android应用的开发和调试来说,完全可以满足。

一、Android应用程序的database目录

Android应用程序,如果需要使用数据库来对数据进行持久化,一定会在应用的目录下生成一个database文件夹,用以存放db文件,如下所示。

其中,.db文件,为应用程序进行数据持久化的数据库文件;而.db-journal文件,则是系统自动生成的日志文件,用于数据库在进行事务时的回滚操作,一般情况下,该文件的大小为0。

pixel:/data/data/com.example.demo/databases # ls -al
total 60
drwxrwx--x 2 u0_a215 u0_a215  4096 2020-03-14 10:25 .
drwx------ 6 u0_a215 u0_a215  4096 2020-03-14 10:25 ..
-rw-rw---- 1 u0_a215 u0_a215 49152 2020-03-14 10:40 demo.db
-rw-rw---- 1 u0_a215 u0_a215     0 2020-03-14 10:40 demo.db-journal

二、使用sqlite3打开db文件

使用sqlite3打开db文件时,可以指定打开的方式为“可写模式”或“只读模式”。(某些旧版本的sqlite3可能没有readonly选项)

# 可写模式打开db文件
pixel:/data/data/com.example.demo/databases # sqlite3 demo.db
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> # 只读模式打开db文件
pixel:/data/data/com.example.demo/databases # sqlite3 -readonly demo.db
SQLite version 3.28.0 2019-04-16 19:49:53
Enter ".help" for usage hints.
sqlite> 

三、退出sqlite3模式

退出sqlite3有三种方式,我们这里比较推荐前两种

# 使用".exit"
sqlite>.exit
pixel:/data/data/com.example.demo/databases # # 使用".quit"命令
sqlite>.quit
pixel:/data/data/com.example.demo/databases # // 连续按三次"Ctrl + C"
sqlite> ^C^C^C
pixel:/data/data/com.example.demo/databases # 

四、sqlite3的几种显示模式

sqlite3在显示数据时,有10种模式,如下所示。

sqlite> .mode mode_name
mode_name list:ascii    Columns/rows delimited by 0x1F and 0x1E   # 以ASCII码显示,可能会是乱码csv      Comma-separated values                    # 以"逗号"分隔column   Left-aligned columns.  (See .width)       # 以左对齐方式显示html     HTML <table> code                         # 以html格式显示insert   SQL insert statements for TABLE           # 以SQL语句形式展示数据是如何插入的line     One value per line                        # 单行显示,并显示每个值的变量名list     Values delimited by "|"                   # 以"|"分隔,这是sqlite3的默认模式quote    Escape answers as for SQL                 # 类似"insert"模式,但该模式只包含数据插入的内容,但不包含SQL语法tabs     Tab-separated values                      # 以"tab"分隔tcl      TCL list elements                         # 将每个值以"双引号"引用,并用空格分隔

我相信,大部分同学在看了上面的解释以后,都不可能完全体会到这10种模式到底会显示成什么样子。我们下面通过实际的例子来给大家展示一下。

# ascii模式
sqlite> .mode ascii
sqlite> select * from news;
10这是第二条新闻的内容1584793640734第二条新闻# csv模式
sqlite> .mode csv
sqlite> select * from news;
1,0,"这是第二条新闻的内容",1584793640734,"第二条新闻"# column模式
sqlite> .mode column
sqlite> select * from news;
1           0             这是第二条新闻的内容                      1584793640734  第二条新闻          # html模式
sqlite> .mode html
sqlite> select * from news;
<TR><TD>1</TD>
<TD>0</TD>
<TD>这是第二条新闻的内容</TD>
<TD>1584793640734</TD>
<TD>第二条新闻</TD>
</TR># insert模式
sqlite> .mode insert
sqlite> select * from news;
INSERT INTO "table" VALUES(1,0,'这是第二条新闻的内容',1584793640734,'第二条新闻');# line模式
sqlite> .mode line
sqlite> select * from news;id = 1
commentcount = 0content = 这是第二条新闻的内容publishdate = 1584793640734title = 第二条新闻# list模式
sqlite> .mode list
sqlite> select * from news;
1|0|这是第二条新闻的内容|1584793640734|第二条新闻# quote模式
sqlite> .mode quote
sqlite> select * from news;
1,0,'这是第二条新闻的内容',1584793640734,'第二条新闻'# tabs模式
sqlite> .mode tabs
sqlite> select * from news;
1   0   这是第二条新闻的内容  1584793640734   第二条新闻# tcl模式
sqlite> .mode tcl
sqlite> select * from news;
"1" "0" "\350\277\231\346\230\257\347\254\254\344\272\214\346\235\241\346\226\260\351\227\273\347\232\204\345\206\205\345\256\271" "1584793640734" "\347\254\254\344\272\214\346\235\241\346\226\260\351\227\273"

通过上面的演示,我们可以很清楚的看到,同样的数据,分别以这10种模式展示出来的样子。其中我们比较常用的模式是list和line。其中list模式,是sqlite3所使用的默认模式,使用"|"对数据进行分隔,每行即为表中的一组数据,十分简洁;但其弊端是,无法得知,被"|"分隔的每个数据,代表表中的哪一列,不够清晰。而line模式,每行只展示一个数据,且会指出该数据在表中的列名,十分清晰;但同样带来的弊端是,如果表的列很多,则打印表中的一行数据,需要占用大量的篇幅,不够简洁。

五、使用“.table”命令查看db文件中的所有表

sqlite> .table
android_metadata  news
comment

可以看到,db中共有三张表,其中“news”和“comment”两个表是我们在代码中创建出来的表。而剩下的“android_metadata”,是系统自动创建的。有关这张表的内容,我们会在后面讲到。

六、对表做CURD操作

对表做CURD操作与我们在数据库软件中使用SQL语句完全一样,这里我们只举几个简单的例子,不熟悉SQL语句的同学,可以自行百度,该部分内容不在我们本篇文章的讲解范围之内。

注意,如果打开db文件时,使用了-readonly参数,则只能对表进行查询操作,不能执行insert、delete和update操作。

# 查询"news"表,得到一条数据
sqlite> select * from news;id = 1
commentcount = 2content = 这是第一条新闻的内容publishdate = 1584793640734title = 第一条新闻# 查询"news"表中的数据个数
sqlite> select count(*) from news;
count(*) = 1# 向"news"表中插入一条数据
sqlite> insert into "news" values(2,0,'这是第二条新闻的内容',1584793642000,'第二条新闻');# 查询"news"表,得到两条数据
sqlite> select * from news;id = 1
commentcount = 2content = 这是第一条新闻的内容publishdate = 1584793640734title = 第一条新闻id = 2
commentcount = 0content = 这是第二条新闻的内容publishdate = 1584793642000title = 第二条新闻# 从"news"中删除"id"为1的数据
sqlite> delete from 'news' where id=1;# 查询"news"表,只剩下"id"为2的数据
sqlite> select * from news;id = 2
commentcount = 0content = 这是第三条新闻的内容publishdate = 1584793642000title = 第二条新闻# 更新"news"中"id"为2的数据,将commentcount列的值改为99
sqlite> update 'news' set commentcount=99 where id=2;# 查询"news"表,"id"为2的数据的commentcount列的值变为99
sqlite> select * from news;id = 2
commentcount = 99content = 这是第二条新闻的内容publishdate = 1584793642000title = 第二条新闻

至此,使用sqlite3对db进行基本操作的讲解,就告一段落了。但本文还没有结束,如果你觉得以上的操作已经完全能够满足你的需求,那就可以到此为止了。当然,如果你希望了解更多,欢迎继续往下阅读。

七、查看表的结构及建表语句

1. 使用“pragma table_info(table_name)”命令查看表结构

       通过“pragma table_info(table_name) ”命令,我们可以很清晰的看到表的接口,和其中每列的各种属性。

sqlite> pragma table_info(news);cid = 0           # 列IDname = id          # 列名type = integer     # 数据类型notnull = 0           # 是否可以为空
dflt_value =             # 默认值pk = 1           # 是否为主键cid = 1name = commentcounttype = integernotnull = 0
dflt_value = pk = 0cid = 2name = contenttype = textnotnull = 0
dflt_value = pk = 0cid = 3name = publishdatetype = integernotnull = 0
dflt_value = pk = 0cid = 4name = titletype = textnotnull = 0
dflt_value = pk = 0

但有时候,想将表的结构,分享给其他人时,如果拷贝这么一大堆内容,其他人在看起来的时候,也会很吃力,有没有什么办法,可以得到建表时所使用的语句呢?当然可以,我们继续往下看。

       2. 查看建表语句

想要查询db的建表语句,有两种方式:

       方法一  使用“.schema”命令查看建表语句

sqlite> .schema
# "android_metadata"表的建表语句
CREATE TABLE android_metadata (locale TEXT);
# "news"表的建表语句
CREATE TABLE news (id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text);
# "comment"表的建表语句
CREATE TABLE comment (id integer primary key autoincrement,content text, publishdata integer, news_id integer);

如果只想查看某一张表的建表语句,我们可以指定表名,以得到更简洁的结果

# 执行表名以得到某一张表的建表语句
sqlite> .schema news
CREATE TABLE news (id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text);# 使用"--indent"参数,可以得到pretty-printing
sqlite> .schema --indent comment
CREATE TABLE comment(id integer primary key autoincrement,content text,publishdata integer,news_id integer
);# 注意,不要加分号,否则不会打印出任何信息
sqlite> .schema news;
sqlite> 

方法二  SQLite创建数据库时,会建立一张特殊的表“sqlite_master”,称为系统表(也有说法叫内置表),用以保存每张表的建表语句。我们可以通过查询该表的内容,来获得建表语句。

sqlite> select * from sqlite_master;type = tablename = android_metadata
tbl_name = android_metadata
rootpage = 3sql = CREATE TABLE android_metadata (locale TEXT)type = tablename = sqlite_sequence
tbl_name = sqlite_sequence
rootpage = 4sql = CREATE TABLE sqlite_sequence(name,seq)type = tablename = news
tbl_name = news
rootpage = 5sql = CREATE TABLE news (id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text)type = indexname = sqlite_autoindex_news_1
tbl_name = news
rootpage = 6type = tablename = comment
tbl_name = comment
rootpage = 7sql = CREATE TABLE comment (id integer primary key autoincrement,content text, publishdata integer, news_id integer)

其中,的字段含义如下所示:

type        # 记录了项目的类型,如table、index、view、trigger。
name        # 记录了项目的名称,如表名、索引名等。
tbl_name    # 记录所从属的表名,如索引所在的表名。对于表来说,该列就是表名本身。
rootpage    # 记录项目在数据库页中存储的编号。对于视图和触发器,该列值为0或者NULL。
sql         # 记录创建该项目的SQL语句。

当然,我们也可以只查询某一张表的信息,可以得到更简洁的信息

sqlite> select * from sqlite_master where name='news';type = tablename = news
tbl_name = news
rootpage = 6sql = CREATE TABLE news (id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text)

相比于方法一,方法二中查询到的信息更全面。同时,也引出了几个系统默认创建的表,它们分别是“android_metadata”,“sqlite_sequence”和“sqlite_master”。

其中“sqlite_master”表,我们在本节已经介绍过了,可以通过其查看每张表的建表语句,后面不再赘述。

“android_metadata”在前面我们使用“.table”命令列出数据库中的表时,已经见到过了,但尚未对其进行分析讲解;而“sqlite_sequence”,我们至今还没有提到过,下面,我们就来对后两张表进行逐一分析。

. 系统创建的表

1. “android_metadata”

首先,我们来看一下这张表的建表语句和表中存储的内容。

# 建表语句
sqlite> .schema android_metadata
CREATE TABLE android_metadata (locale TEXT);# 存储内容
sqlite> select * from android_metadata;
locale = zh_CN

其实,这样一看,“android_metadata”表的作用就很清晰了,它是用来存储“默认语言环境”的,其中“zh_CN”就表示“简体中文,中华人民共和国”。当然,如果手机的默认语言环境如果是美式英语的话,那“locale”的值将会是“en-US”。

关于“android_metadata”表和“Locale”的内容,如果大家有兴趣,可以自行阅读源码中的“SQLiteConnection.java”和“Locale.java”文件。

2. “sqlite_sequence”

老样子,还是先来看建表语句和表中存储的内容。

# 建表语句
sqlite> .schema sqlite_sequence
CREATE TABLE sqlite_sequence(name,seq)# 存储内容
sqlite> select * from sqlite_sequence;name = commentseq = 2name = newsseq = 2

“name”字段,没什么可以说的,就是表名。

而“seq”是做什么用的呢?我们先来分别查询一下这两张表中的数据。

# 查询"news"表中的数据,只有一条记录
sqlite> select * from news;id = 2
commentcount = 99content = 这是第三条新闻的内容publishdate = 1584793642000title = 第三条新闻# 查询"comment"表中的数据,有两条记录
sqlite> select * from comment;id = 1content = 好评!
publishdata = 1584793640700news_id = 2id = 2content = 赞一个!
publishdata = 1584793640719news_id = 2

“comment”表中,有两条记录,与“sqlite_sequence”表中关于“comment”的“seq”的值吻合,但“news”表中只有一条,为什么“sqlite_sequence”表中关于“news”的“seq”值也是2呢?

注意观察,我们发现,无论“news”表,还是“comment”表,其最大的id值,均为2。那是不是说,“sqlite_sequence”表中记录的“seq”值,有可能是每张表中id的最大值呢?我们不妨来做个实验。

# 像"new"表中插入一条id为8的数据
sqlite> INSERT INTO "news" VALUES(8,1002,'This is Only for Test',123123123,'Test');# 查询"news"表中的数据
sqlite> select * from news;id = 2
commentcount = 99content = 这是第三条新闻的内容publishdate = 1584793642000title = 第三条新闻id = 8
commentcount = 1002content = This is Only for Testpublishdate = 123123123title = Test# 再次查询"sqlite_sequence"表中的数据
sqlite> select * from sqlite_sequence;name = commentseq = 2name = newsseq = 8

诶,“sqlite_sequence”中关于“news”表的“seq”值果然变为8了,说明我们之前的猜想是正确的。那么,为什么要记录这个值呢?我们不妨再来看看“news”表和“comment”表的建表语句。

# "news"表的建表语句
CREATE TABLE news (id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text);# "comment"表的建表语句
CREATE TABLE comment (id integer primary key autoincrement,content text, publishdata integer, news_

发现没有,两张表的id值,均为autoincrement类型。因此,数据库需要在每次插入数据时,记录每张表当前的id值,以便在下次向表中插入数据时,对该值进行+1操作。

至此,所有要分析的内容都已经结束了,希望本文能对那些还不太熟悉sqlite3使用方法的同学带来一些帮助。时间仓促,文中难免会有疏漏,如有错误,欢迎大家予以指正。

Android SQLite 数据库常用命令相关推荐

  1. android SQLite数据库的使用

    今天,简单讲讲android如何使用SQLite数据库.  最近,自己在做一个功能时又用到了SQLite数据库,发现自己还是掌握的不很全面.其实之前的app里面也一直用到了数据库,但是自己没有花时 ...

  2. Android SQLite 数据库详细介绍

    Android SQLite 数据库详细介绍我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用软 ...

  3. SQLite数据库常用语句及MAC上的SQLite可视化工具MeasSQLlite使用

    SQLite数据库常用语句及MAC上的SQLite可视化工具MeasSQLlite使用 一.引言 在移动开发中,通常会用到一些小型的数据库进行数据管理.SQLite是一款十分小巧便捷的数据库,在iOS ...

  4. MySQL 数据库常用命令—where like union 排序 分组 连接

    引言 本篇博客对 MySQL 数据库的一些命令进行分享. where 语句 基本语法规则: select field1, field2,...fieldN from table_name1, tabl ...

  5. MySQL 数据库常用命令小结

    MySQL 数据库常用命令 1.MySQL常用命令 create database name; 创建数据库 use databasename; 选择数据库 drop database name 直接删 ...

  6. android 数据库表格数据库数据库中,Android SQLite数据库中的表详解

    Android SQLite数据库 前言 以前写PHP的时候,内置了print_r()和var_dump()两个函数用于打印输出任意类型的数据内部结构,现在做Android的开发,发现并没有这种类似的 ...

  7. 利用SQLChiper对Android SQLite数据库加密

    利用SQLChiper对Android SQLite数据库加密 前言: 上篇文章讲了Android studio+SQLCipher加密SQLite数据库的几个坑,跳过这几个坑,那么SQLCipher ...

  8. android 获取位置数据库,尝试从webview获取位置时,Android“SQLite数据库无法从/CachedGeoposition.db加载”错误...

    我正在创建一个使用webkit和chrome客户端的android应用程序.我希望能够在网页请求时获取当前位置.我设置的网页适用于普通浏览器就好了.然而,当我尝试访问该网页WebKit中,我不断收到此 ...

  9. hive mysql命令,Hive数据库常用命令

    收藏一些Hive数据库常用命令,方便平时准备测试数据集. 查看库.创建普通Hive表: show databases; user lch_databases; show tables; create ...

最新文章

  1. springboot2 cookie的token如何放入请求头_Spring MVC 到底是如何工作的
  2. day27 CRM delete action 嵌入CRM
  3. linux 编译环境包,linux上war包编译环境搭建
  4. RabbitMQ入门教程
  5. java栈匹配括号_使用到栈结构的一个表达式括号匹配检查类
  6. 音视频多媒体开发基础概述之颜色空间(1)CIE色度模型 RGB颜色空间
  7. 超级电容模组电压不均衡特性分析
  8. AWT绘图工具Graphics
  9. 炎黄盈动易鲸云低代码平台,全面助推企业数字化转型升级
  10. 单细胞测序流程(九)单细胞的GO圈图
  11. 利用计算机模拟函数图像,计算机模拟实验在教学中的应用论文(2)
  12. spring boot微服务项目搭建
  13. 农用地包括哪些地类_农用地、基本农田、建设用地,不同类型的土地性质要怎么利用...
  14. display:inline-bock的注意
  15. 单波段彩色变换(伪彩色密度分割)
  16. LogicFlow插件-常用内置
  17. 英语发音规则---E字母(总结)-[复习中]
  18. 笔记本电脑如何查看网络计算机,笔记本自带网卡吗_查看笔记本电脑有无无线网卡的步骤-win7之家...
  19. R语言线性判别分析(LDA),二次判别分析(QDA)和正则判别分析(RDA)
  20. 【异常处理】com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@390508 --nb

热门文章

  1. 软件测试基础-Web前端(二)
  2. 在xp系统电脑上建立宽带连接服务器吗,windows 7与windows xp创建宽带连接的方法-电脑教程...
  3. Unity CardboardSDK解析
  4. 彻底卸载secureCRT
  5. 洛谷——P1348 Couple number(java实现)
  6. 理解Anchor、RPN真值与预测量、RPN卷积网络
  7. R语言 sub()用法
  8. springBoot的shiro的简单项目部署
  9. 蜗牛星际C单下实现黑群的局域网唤醒
  10. windows显示WiFi密码