美文网首页Android数据库高手秘籍
Android数据库高手(一)SQLite命令

Android数据库高手(一)SQLite命令

作者: as_pixar | 来源:发表于2019-12-24 18:36 被阅读0次

    咱们熟练地操作数据库,弄懂SQL语言是很简单的,精通需要花点时间。SQL是个啥?
    SQL(Structured Query Language)标准数据库查询语言,所有关系型数据库都支持。每种数据库对SQL语言的支持与标准存在着细微的不同。咱们只要把重点放在SQLite(轻量级数据库)上就可以了。咱们使用模拟器对SQLite支持的各种命令进行演示,如果你想用手机的话也可以,但要确保你的手机已经Root。

    我把模拟器先连接上了电脑,然后在命令行输入adb shell进入控制台,如下图所示:

    C:\Users\nihao>adb devices
    List of devices attached
    2PFNW19109015908        unauthorized
    emulator-5554   device
    
    C:\Users\nihao>adb -s emulator-5554 shell
    root@generic_x86:/ #
    

    注意#符号表示我们当前是超级用户了,如果显示的是$符号,表示当前只是普通用户而已,这时还需要输入su命令切换一下用户身份才行。adb -s 设备序列号 shell 来选择模拟器 (adb -s 设备序列号 shell)

    我们有超级用户权限之后,可以搞事情了,咱们先查看系统自带的联系人表。进入到/data/data目录下,如下图所示:

    root@generic_x86:/ # cd data/data
    root@generic_x86:/data/data #
    

    所有应用程序的本地存储文件都是存放在这个目录下面。要让不同应用程序之间的数据容易区别开来,Android是使用应用程序包名进行分开管理,每个应用程序的本地存储文件都会存放在自己应用程序包名的那个目录下,这里我们ls一下看看有多少子目录:

    root@generic_x86:/data/data # ls
    com.android.backupconfirm
    com.android.browser
    com.android.calculator2
    com.android.camera
    com.android.captiveportallogin
    com.android.certinstaller
    com.android.contacts
    com.android.customlocale2
    com.android.defcontainer
    com.android.deskclock
    com.android.development
    com.android.development_settings
    com.android.dialer
    com.android.documentsui
    com.android.dreams.basic
    com.android.emulator.smoketests
    com.android.exchange
    com.android.externalstorage
    com.android.fallback
    com.android.gallery
    com.android.gesture.builder
    com.android.htmlviewer
    com.android.inputdevices
    com.android.inputmethod.latin
    com.android.keychain
    com.android.location.fused
    com.android.managedprovisioning
    com.android.mms
    com.android.mms.service
    com.android.music
    com.android.netspeed
    com.android.packageinstaller
    com.android.pacprocessor
    com.android.phone
    com.android.printspooler
    com.android.protips
    com.android.providers.calendar
    com.android.providers.contacts
    com.android.providers.downloads
    com.android.providers.downloads.ui
    com.android.providers.media
    com.android.providers.settings
    com.android.providers.telephony
    com.android.providers.userdictionary
    com.android.proxyhandler
    com.android.sdksetup
    com.android.server.telecom
    com.android.settings
    com.android.sharedstoragebackup
    com.android.shell
    com.android.smoketest
    com.android.smoketest.tests
    com.android.soundrecorder
    com.android.speechrecorder
    com.android.systemui
    com.android.vending
    com.android.vpndialogs
    com.android.wallpaper.livepicker
    com.android.webview
    com.android.widgetpreview
    com.example.android.apis
    com.example.android.livecubes
    com.example.android.softkeyboard
    com.google.android.apps.maps
    com.google.android.calendar
    com.google.android.gm
    com.google.android.gms
    com.google.android.googlequicksearchbox
    com.google.android.gsf
    com.google.android.gsf.login
    com.google.android.launcher
    com.google.android.play.games
    com.google.android.street
    com.google.android.syncadapters.contacts
    com.svox.pico
    jp.co.omronsoft.openwnn
    org.litepal.litepalsample
    root@generic_x86:/data/data #
    

    OK,确实有很多,毕竟手机上所有的应用程序都在这里。其中,com.android.providers.contacts中存放的就是联系人的相关数据,我们进入到这个目录再ls一下:

    root@generic_x86:/data/data # cd com.android.providers.contacts
    root@generic_x86:/data/data/com.android.providers.contacts # ls
    cache
    databases
    files
    lib
    shared_prefs
    root@generic_x86:/data/data/com.android.providers.contacts #
    

    可以看到,目前有databases、files、lib和shared_prefs这几个子目录。其中databases肯定是用于存放数据库文件的,files是用于存放普通文本文件的,lib是用于存放so库的,shared_prefs则是用于存放shared文件的。

    接着进入到databases目录中,再ls:

    root@generic_x86:/data/data/com.android.providers.contacts # cd databases
    root@generic_x86:/data/data/com.android.providers.contacts/databases #
    ls
    contacts2.db
    contacts2.db-journal
    profile.db
    profile.db-journal
    root@generic_x86:/data/data/com.android.providers.contacts/databases #
    

    其中后缀名为journal的文件是日志文件,我们不用管,contacts2.db和profile.db才是真正的数据库文件,可以使用sqlite3命令来打开数据库,如下图所示:

    sqlite3 contacts2.db
    SQLite version 3.8.6.1 2015-05-21 17:24:32
    Enter ".help" for usage hints.
    sqlite>
    

    数据库已打开,那么我们怎么才能知道当前数据库中有哪些表呢?很简单,.table命令就可以做到了:

    sqlite> .table
    _sync_state               phone_lookup              view_data_usage_stat
    _sync_state_metadata      photo_files               view_entities
    accounts                  properties                view_groups
    agg_exceptions            raw_contacts              view_raw_contacts
    android_metadata          search_index              view_raw_entities
    calls                     search_index_content      view_stream_items
    contacts                  search_index_docsize      view_v1_contact_methods
    data                      search_index_segdir       view_v1_extensions
    data_usage_stat           search_index_segments     view_v1_group_membership
    default_directory         search_index_stat         view_v1_groups
    deleted_contacts          settings                  view_v1_organizations
    directories               status_updates            view_v1_people
    groups                    stream_item_photos        view_v1_phones
    mimetypes                 stream_items              view_v1_photos
    name_lookup               v1_settings               visible_contacts
    nickname_lookup           view_contacts             voicemail_status
    packages                  view_data
    sqlite>
    

    竟然有这么多张表!联系人的数据结构挺热闹,很多的数据都是分表存储的。我们随便挑一张表,比如说accounts表,如果我想知道这张表中有哪些列应该怎么办呢?在MySQL中可以使用desc accounts这个命令,但SQLite却不认识这个命令,毕竟它们是有差异化的。SQLite中可以使用pragma table_info(TABLE_NAME)这个命令来查看表的数据结构,如下图所示:

    sqlite> pragma table_info(accounts);
    0|_id|INTEGER|0||1
    1|account_name|TEXT|0||0
    2|account_type|TEXT|0||0
    3|data_set|TEXT|0||0
    sqlite>
    

    一共显示了四条结果,表示accounts表中共有四列。但是,所有的字段都缩在了一行里面,并用“|”符号分隔,这样我们很难看出每个字段的含义。很简单,只需要换一种显示模式就行了,比如说line模式就挺不错的。输入.mode line命令切换显示模式,然后重新运行pragma命令,结果如下图所示:

    sqlite> .mode line
    sqlite> pragma table_info(accounts);
           cid = 0
          name = _id
          type = INTEGER
       notnull = 0
    dflt_value =
            pk = 1
    
           cid = 1
          name = account_name
          type = TEXT
       notnull = 0
    dflt_value =
            pk = 0
    
           cid = 2
          name = account_type
          type = TEXT
       notnull = 0
    dflt_value =
            pk = 0
    
           cid = 3
          name = data_set
          type = TEXT
       notnull = 0
    dflt_value =
            pk = 0
    sqlite>
    

    好多了吧?四个列名分别是_id、account_name、account_type和data_set,数据类型Integer,剩下都是TEXT(字符串),允许为空,并且都不是主键。好,那我现在想查一查accounts表中的数据呢?这就太简单了,使用select语句就可以了,如下所示:

    sqlite> select * from accounts;
    sqlite>
    

    除了查询命令之外,还有其它的增删改命令都和标准的SQL语法是相同的,即insert、delete和update,由于比较简单,我就不再赘述了。比较值得一提的是,每个SQLite数据库中都还有一个隐藏的sqlite_master表,这里记载了当前数据库中所有表的建表语句,可以使用select * from sqlite_master命令进行查看:

    sqlite> select * from sqlite_master
       ...> ;
        type = table
        name = android_metadata
    tbl_name = android_metadata
    rootpage = 3
         sql = CREATE TABLE android_metadata (locale TEXT)
    
        type = table
        name = _sync_state
    tbl_name = _sync_state
    rootpage = 4
         sql = CREATE TABLE _sync_state (_id INTEGER PRIMARY KEY,account_name TEXT NOT NULL,account_type TEXT NOT NULL,data TEXT,UNIQUE(account_name, account_type))
    
        type = index
        name = sqlite_autoindex__sync_state_1
    tbl_name = _sync_state
    rootpage = 5
         sql =
    
        type = table
        name = _sync_state_metadata
    tbl_name = _sync_state_metadata
    rootpage = 6
         sql = CREATE TABLE _sync_state_metadata (version INTEGER)
    
        type = table
        name = properties
    tbl_name = properties
    rootpage = 7
         sql = CREATE TABLE properties (property_key TEXT PRIMARY KEY, property_value TEXT )
    
        type = index
        name = sqlite_autoindex_properties_1
    tbl_name = properties
    rootpage = 8
         sql =
    
        type = table
        name = accounts
    tbl_name = accounts
    rootpage = 9
         sql = CREATE TABLE accounts (_id INTEGER PRIMARY KEY AUTOINCREMENT,account_name TEXT, account_type TEXT, data_set TEXT)
    
        type = table
        name = sqlite_sequence
    tbl_name = sqlite_sequence
    rootpage = 10
         sql = CREATE TABLE sqlite_sequence(name,seq)
    
        type = table
        name = contacts
    tbl_name = contacts
    rootpage = 11
         sql = CREATE TABLE contacts (_id INTEGER PRIMARY KEY AUTOINCREMENT,name_raw_contact_id INTEGER REFERENCES raw_contacts(_id),photo_id INTEGER REFERENCES data(_id),photo_file_id INTEGER REFERENCES photo_files(_id),custom_ringtone TEXT,send_to_voicemail INTEGER NOT NULL DEFAULT 0,times_contacted INTEGER NOT NULL DEFAULT 0,last_time_contacted INTEGER,starred INTEGER NOT NULL DEFAULT 0,pinned INTEGER NOT NULL DEFAULT 0,has_phone_number INTEGER NOT NULL DEFAULT 0,lookup TEXT,status_update_id INTEGER REFERENCES data(_id),contact_last_updated_timestamp INTEGER)
    

    结果太多了是不是?一屏根本就显示不下嘛。不要着急,别忘了我们使用的是select命令,可以使用where语句来过滤出我们想要查询的那部分内容,如下图所示:

    sqlite> select * from sqlite_master where name='accounts';
        type = table
        name = accounts
    tbl_name = accounts
    rootpage = 9
         sql = CREATE TABLE accounts (_id INTEGER PRIMARY KEY AUTOINCREMENT,account_name TEXT, account_type TEXT, data_set TEXT)
    sqlite>
    

    OK,CREATE TABLE accounts (_id INTEGER PRIMARY KEY AUTOINCREMENT,account_name TEXT, account_type TEXT, data_set TEXT)这就是accounts表的建表语句了,通过这种方式我们可以查询到任意一张表的建表语句,从而对我们学习和分析数据库表结构有所帮助。

    有些朋友会觉得,每次都要输入select命令来查询表中的数据太麻烦了。没错,而且还要保证手机是连接在电脑上的时候才能查询,确实太不方便。幸运的是,有些手机软件已经提供了数据库表查询的功能,使得我们随时随地都可以方便地查看数据库中的数据,比如Root Explorer这款软件就不错。

    仍然是确保你的手机已经Root,然后安装Root Explorer,打开软件之后按照我们前面介绍的路径,进入/data/data/com.android.providers.contacts/databases,点击contacts2.db数据库,选择内置数据库查看器,然后随便点击一张表就可以查看到里面的数据了!给力了不,还有很多其它的工具,嗨了吧!

    Android Studio 3.0新加入的Device File Explorer
    image.png

    图形化查看联系人目录,选中某个文件,可以导出到咱们的电脑桌面,很给力

    Android Studio 安装数据库插件

    image.png
    安装成功之后重启Android Studio使用数据库插件

    点击左侧栏的DB Browser


    image.png image.png image.png

    使用这种方法,我们可以随时查看数据库表中的最新数据,直观又方便,在程序开发的时候可以起到非常大的帮助。

    好了,今天的讲解就到这里,下篇文章当中我将带领大家探究Android数据库中更多的奥秘。感兴趣的朋友请继续阅读 Android数据库高手专题

    喜欢就点个赞把

    相关文章

      网友评论

        本文标题:Android数据库高手(一)SQLite命令

        本文链接:https://www.haomeiwen.com/subject/kwtfoctx.html