Android SQLite 数据库常用命令

转载请注明出处: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。


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

 

二、使用sqlite3打开db文件

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


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

 

三、退出sqlite3模式

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


   
   
  1. # 使用".exit"
  2. sqlite>. exit
  3. pixel:/data/data/com.example.demo/databases #
  4. # 使用".quit"命令
  5. sqlite>.quit
  6. pixel:/data/data/com.example.demo/databases #
  7. // 连续按三次 "Ctrl + C"
  8. sqlite> ^C^C^C
  9. pixel:/data/data/com.example.demo/databases #

 

四、sqlite3的几种显示模式

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


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

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


   
   
  1. # ascii模式
  2. sqlite> .mode ascii
  3. sqlite> select * from news;
  4. 10这是第二条新闻的内容1584793640734第二条新闻
  5. # csv模式
  6. sqlite> .mode csv
  7. sqlite> select * from news;
  8. 1,0, "这是第二条新闻的内容",1584793640734, "第二条新闻"
  9. # column模式
  10. sqlite> .mode column
  11. sqlite> select * from news;
  12. 1 0 这是第二条新闻的内容 1584793640734 第二条新闻
  13. # html模式
  14. sqlite> .mode html
  15. sqlite> select * from news;
  16. <TR><TD>1</TD>
  17. <TD>0</TD>
  18. <TD>这是第二条新闻的内容</TD>
  19. <TD>1584793640734</TD>
  20. <TD>第二条新闻</TD>
  21. </TR>
  22. # insert模式
  23. sqlite> .mode insert
  24. sqlite> select * from news;
  25. INSERT INTO "table" VALUES(1,0, '这是第二条新闻的内容',1584793640734, '第二条新闻');
  26. # line模式
  27. sqlite> .mode line
  28. sqlite> select * from news;
  29. id = 1
  30. commentcount = 0
  31. content = 这是第二条新闻的内容
  32. publishdate = 1584793640734
  33. title = 第二条新闻
  34. # list模式
  35. sqlite> .mode list
  36. sqlite> select * from news;
  37. 1|0|这是第二条新闻的内容|1584793640734|第二条新闻
  38. # quote模式
  39. sqlite> .mode quote
  40. sqlite> select * from news;
  41. 1,0, '这是第二条新闻的内容',1584793640734, '第二条新闻'
  42. # tabs模式
  43. sqlite> .mode tabs
  44. sqlite> select * from news;
  45. 1 0 这是第二条新闻的内容 1584793640734 第二条新闻
  46. # tcl模式
  47. sqlite> .mode tcl
  48. sqlite> select * from news;
  49. "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文件中的所有表


   
   
  1. sqlite> .table
  2. android_metadata news
  3. comment

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

 

六、对表做CURD操作

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

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


   
   
  1. # 查询"news"表,得到一条数据
  2. sqlite> select * from news;
  3. id = 1
  4. commentcount = 2
  5. content = 这是第一条新闻的内容
  6. publishdate = 1584793640734
  7. title = 第一条新闻
  8. # 查询"news"表中的数据个数
  9. sqlite> select count(*) from news;
  10. count(*) = 1
  11. # 向"news"表中插入一条数据
  12. sqlite> insert into "news" values(2,0, '这是第二条新闻的内容',1584793642000, '第二条新闻');
  13. # 查询"news"表,得到两条数据
  14. sqlite> select * from news;
  15. id = 1
  16. commentcount = 2
  17. content = 这是第一条新闻的内容
  18. publishdate = 1584793640734
  19. title = 第一条新闻
  20. id = 2
  21. commentcount = 0
  22. content = 这是第二条新闻的内容
  23. publishdate = 1584793642000
  24. title = 第二条新闻
  25. # 从"news"中删除"id"为1的数据
  26. sqlite> delete from 'news' where id=1;
  27. # 查询"news"表,只剩下"id"为2的数据
  28. sqlite> select * from news;
  29. id = 2
  30. commentcount = 0
  31. content = 这是第三条新闻的内容
  32. publishdate = 1584793642000
  33. title = 第二条新闻
  34. # 更新"news"中"id"为2的数据,将commentcount列的值改为99
  35. sqlite> update 'news' set commentcount=99 where id=2;
  36. # 查询"news"表,"id"为2的数据的commentcount列的值变为99
  37. sqlite> select * from news;
  38. id = 2
  39. commentcount = 99
  40. content = 这是第二条新闻的内容
  41. publishdate = 1584793642000
  42. title = 第二条新闻

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

 

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

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

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


   
   
  1. sqlite> pragma table_info(news);
  2. cid = 0 # 列ID
  3. name = id # 列名
  4. type = integer # 数据类型
  5. notnull = 0 # 是否可以为空
  6. dflt_value = # 默认值
  7. pk = 1 # 是否为主键
  8. cid = 1
  9. name = commentcount
  10. type = integer
  11. notnull = 0
  12. dflt_value =
  13. pk = 0
  14. cid = 2
  15. name = content
  16. type = text
  17. notnull = 0
  18. dflt_value =
  19. pk = 0
  20. cid = 3
  21. name = publishdate
  22. type = integer
  23. notnull = 0
  24. dflt_value =
  25. pk = 0
  26. cid = 4
  27. name = title
  28. type = text
  29. notnull = 0
  30. dflt_value =
  31. pk = 0

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

 

       2. 查看建表语句

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

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


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

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


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

 

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


   
   
  1. sqlite> select * from sqlite_master;
  2. type = table
  3. name = android_metadata
  4. tbl_name = android_metadata
  5. rootpage = 3
  6. sql = CREATE TABLE android_metadata (locale TEXT)
  7. type = table
  8. name = sqlite_sequence
  9. tbl_name = sqlite_sequence
  10. rootpage = 4
  11. sql = CREATE TABLE sqlite_sequence(name, seq)
  12. type = table
  13. name = news
  14. tbl_name = news
  15. rootpage = 5
  16. sql = CREATE TABLE news ( id integer primary key autoincrement,commentcount integer, content text, publishdate integer, title text)
  17. type = index
  18. name = sqlite_autoindex_news_1
  19. tbl_name = news
  20. rootpage = 6
  21. type = table
  22. name = comment
  23. tbl_name = comment
  24. rootpage = 7
  25. sql = CREATE TABLE comment ( id integer primary key autoincrement,content text, publishdata integer, news_id integer)

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


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

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


   
   
  1. sqlite> select * from sqlite_master where name= 'news';
  2. type = table
  3. name = news
  4. tbl_name = news
  5. rootpage = 6
  6. sql = 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”

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


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

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

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

 

       2. “sqlite_sequence”

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


   
   
  1. # 建表语句
  2. sqlite> .schema sqlite_sequence
  3. CREATE TABLE sqlite_sequence(name, seq)
  4. # 存储内容
  5. sqlite> select * from sqlite_sequence;
  6. name = comment
  7. seq = 2
  8. name = news
  9. seq = 2

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

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


   
   
  1. # 查询"news"表中的数据,只有一条记录
  2. sqlite> select * from news;
  3. id = 2
  4. commentcount = 99
  5. content = 这是第三条新闻的内容
  6. publishdate = 1584793642000
  7. title = 第三条新闻
  8. # 查询"comment"表中的数据,有两条记录
  9. sqlite> select * from comment;
  10. id = 1
  11. content = 好评!
  12. publishdata = 1584793640700
  13. news_id = 2
  14. id = 2
  15. content = 赞一个!
  16. publishdata = 1584793640719
  17. news_id = 2

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

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


   
   
  1. # 像"new"表中插入一条id为8的数据
  2. sqlite> INSERT INTO "news" VALUES(8,1002, 'This is Only for Test',123123123, 'Test');
  3. # 查询"news"表中的数据
  4. sqlite> select * from news;
  5. id = 2
  6. commentcount = 99
  7. content = 这是第三条新闻的内容
  8. publishdate = 1584793642000
  9. title = 第三条新闻
  10. id = 8
  11. commentcount = 1002
  12. content = This is Only for Test
  13. publishdate = 123123123
  14. title = Test
  15. # 再次查询"sqlite_sequence"表中的数据
  16. sqlite> select * from sqlite_sequence;
  17. name = comment
  18. seq = 2
  19. name = news
  20. seq = 8

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


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

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

 

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值