咱們熟練地操作數(shù)據(jù)庫杏瞻,弄懂SQL語言是很簡單的晴叨,精通需要花點(diǎn)時(shí)間涂召。SQL是個啥舟陆?
SQL(Structured Query Language)標(biāo)準(zhǔn)數(shù)據(jù)庫查詢語言误澳,所有關(guān)系型數(shù)據(jù)庫都支持。每種數(shù)據(jù)庫對SQL語言的支持與標(biāo)準(zhǔn)存在著細(xì)微的不同秦躯。咱們只要把重點(diǎn)放在SQLite(輕量級數(shù)據(jù)庫)上就可以了脓匿。咱們使用模擬器對SQLite支持的各種命令進(jìn)行演示,如果你想用手機(jī)的話也可以宦赠,但要確保你的手機(jī)已經(jīng)Root。
我把模擬器先連接上了電腦米母,然后在命令行輸入adb shell進(jìn)入控制臺勾扭,如下圖所示:
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:/ #
注意#符號表示我們當(dāng)前是超級用戶了,如果顯示的是$符號铁瞒,表示當(dāng)前只是普通用戶而已妙色,這時(shí)還需要輸入su命令切換一下用戶身份才行。adb -s 設(shè)備序列號 shell 來選擇模擬器 (adb -s 設(shè)備序列號 shell)
我們有超級用戶權(quán)限之后慧耍,可以搞事情了身辨,咱們先查看系統(tǒng)自帶的聯(lián)系人表。進(jìn)入到/data/data目錄下芍碧,如下圖所示:
root@generic_x86:/ # cd data/data
root@generic_x86:/data/data #
所有應(yīng)用程序的本地存儲文件都是存放在這個目錄下面煌珊。要讓不同應(yīng)用程序之間的數(shù)據(jù)容易區(qū)別開來,Android是使用應(yīng)用程序包名進(jìn)行分開管理泌豆,每個應(yīng)用程序的本地存儲文件都會存放在自己應(yīng)用程序包名的那個目錄下定庵,這里我們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,確實(shí)有很多,畢竟手機(jī)上所有的應(yīng)用程序都在這里蔬浙。其中猪落,com.android.providers.contacts中存放的就是聯(lián)系人的相關(guān)數(shù)據(jù),我們進(jìn)入到這個目錄再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肯定是用于存放數(shù)據(jù)庫文件的官疲,files是用于存放普通文本文件的,lib是用于存放so庫的庶艾,shared_prefs則是用于存放shared文件的袁余。
接著進(jìn)入到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才是真正的數(shù)據(jù)庫文件,可以使用sqlite3命令來打開數(shù)據(jù)庫煤裙,如下圖所示:
sqlite3 contacts2.db
SQLite version 3.8.6.1 2015-05-21 17:24:32
Enter ".help" for usage hints.
sqlite>
數(shù)據(jù)庫已打開掩完,那么我們怎么才能知道當(dāng)前數(shù)據(jù)庫中有哪些表呢?很簡單硼砰,.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>
竟然有這么多張表且蓬!聯(lián)系人的數(shù)據(jù)結(jié)構(gòu)挺熱鬧,很多的數(shù)據(jù)都是分表存儲的题翰。我們隨便挑一張表恶阴,比如說accounts表,如果我想知道這張表中有哪些列應(yīng)該怎么辦呢豹障?在MySQL中可以使用desc accounts這個命令冯事,但SQLite卻不認(rèn)識這個命令,畢竟它們是有差異化的血公。SQLite中可以使用pragma table_info(TABLE_NAME)這個命令來查看表的數(shù)據(jù)結(jié)構(gòu)昵仅,如下圖所示:
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>
一共顯示了四條結(jié)果,表示accounts表中共有四列累魔。但是摔笤,所有的字段都縮在了一行里面,并用“|”符號分隔垦写,這樣我們很難看出每個字段的含義吕世。很簡單,只需要換一種顯示模式就行了梯投,比如說line模式就挺不錯的寞冯。輸入.mode line命令切換顯示模式渴析,然后重新運(yùn)行pragma命令,結(jié)果如下圖所示:
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漓帚,數(shù)據(jù)類型Integer母债,剩下都是TEXT(字符串),允許為空尝抖,并且都不是主鍵毡们。好,那我現(xiàn)在想查一查accounts表中的數(shù)據(jù)呢昧辽?這就太簡單了衙熔,使用select語句就可以了,如下所示:
sqlite> select * from accounts;
sqlite>
除了查詢命令之外搅荞,還有其它的增刪改命令都和標(biāo)準(zhǔn)的SQL語法是相同的红氯,即insert、delete和update咕痛,由于比較簡單痢甘,我就不再贅述了。比較值得一提的是茉贡,每個SQLite數(shù)據(jù)庫中都還有一個隱藏的sqlite_master表塞栅,這里記載了當(dāng)前數(shù)據(jù)庫中所有表的建表語句,可以使用select * from sqlite_master命令進(jìn)行查看:
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)
結(jié)果太多了是不是腔丧?一屏根本就顯示不下嘛放椰。不要著急,別忘了我們使用的是select命令愉粤,可以使用where語句來過濾出我們想要查詢的那部分內(nèi)容砾医,如下圖所示:
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表的建表語句了科汗,通過這種方式我們可以查詢到任意一張表的建表語句,從而對我們學(xué)習(xí)和分析數(shù)據(jù)庫表結(jié)構(gòu)有所幫助绷雏。
有些朋友會覺得头滔,每次都要輸入select命令來查詢表中的數(shù)據(jù)太麻煩了。沒錯涎显,而且還要保證手機(jī)是連接在電腦上的時(shí)候才能查詢坤检,確實(shí)太不方便。幸運(yùn)的是期吓,有些手機(jī)軟件已經(jīng)提供了數(shù)據(jù)庫表查詢的功能早歇,使得我們隨時(shí)隨地都可以方便地查看數(shù)據(jù)庫中的數(shù)據(jù),比如Root Explorer這款軟件就不錯。
仍然是確保你的手機(jī)已經(jīng)Root箭跳,然后安裝Root Explorer晨另,打開軟件之后按照我們前面介紹的路徑,進(jìn)入/data/data/com.android.providers.contacts/databases谱姓,點(diǎn)擊contacts2.db數(shù)據(jù)庫借尿,選擇內(nèi)置數(shù)據(jù)庫查看器,然后隨便點(diǎn)擊一張表就可以查看到里面的數(shù)據(jù)了!給力了不屉来,還有很多其它的工具路翻,嗨了吧!
Android Studio 3.0新加入的Device File Explorer
圖形化查看聯(lián)系人目錄茄靠,選中某個文件茂契,可以導(dǎo)出到咱們的電腦桌面,很給力
Android Studio 安裝數(shù)據(jù)庫插件
安裝成功之后重啟Android Studio使用數(shù)據(jù)庫插件
點(diǎn)擊左側(cè)欄的DB Browser
使用這種方法慨绳,我們可以隨時(shí)查看數(shù)據(jù)庫表中的最新數(shù)據(jù)掉冶,直觀又方便,在程序開發(fā)的時(shí)候可以起到非常大的幫助儡蔓。
好了郭蕉,今天的講解就到這里,下篇文章當(dāng)中我將帶領(lǐng)大家探究Android數(shù)據(jù)庫中更多的奧秘喂江。感興趣的朋友請繼續(xù)閱讀 Android數(shù)據(jù)庫高手專題
喜歡就點(diǎn)個贊把