数据存储之-SQLite数据库一
概述
- SQLite是一個輕量級的關系型數據庫,運算速度快,占用資源少,很適合在移動設備上使用, 不僅支持標準SQL語法,還遵循ACID(數據庫事務)原則,無需賬號,使用起來非常方便!
- SQLite支持五種數據類型:NULL,INTEGER,REAL(浮點數),TEXT(字符串文本)和BLOB(二進制對象) 。
- 雖然只有五種,但是對于varchar,char等其他數據類型都是可以保存的;因為SQLite有個最大的特點: 你可以各種數據類型的數據保存到任何字段中而不用關心字段聲明的數據類型是什么,比如你 可以在Integer類型的字段中存放字符串,當然除了聲明為主鍵INTEGER PRIMARY KEY的字段只能夠存儲64位整數! 另外, SQLite 在解析CREATE TABLE 語句時, 會忽略 CREATE TABLE 語句中跟在字段名后面的數據類型信息。如下面語句會忽略 name字段的類型信息: CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))
- SQlite通過文件來保存數據庫,一個文件就是一個數據庫,數據庫中又包含多個表格,表格里又有 多條記錄,每個記錄由多個字段構成,每個字段有對應的值,每個值我們可以指定類型,也可以不指定 類型(主鍵除外)
- Android內置的SQLite是SQLite 3版本的~
幾個相關的類:
- SQLiteOpenHelper:抽象類,我們通過繼承該類,然后重寫數據庫創建以及更新的方法, 我們還可以通過該類的對象獲得數據庫實例,或者關閉數據庫!
- SQLiteDatabase:數據庫訪問類:我們可以通過該類的對象來對數據庫做一些增刪改查的操作
- Cursor:游標,有點類似于JDBC里的resultset,結果集!可以簡單理解為指向數據庫中某 一個記錄的指針!
使用SQLiteOpenHelper類創建數據庫與版本管理
對于涉及數據庫的app,我們不可能手動地去給他創建數據庫文件,所以需要在第一次啟用app 的時候就創建好數據庫表;而當我們的應用進行升級需要修改數據庫表的結構時,這個時候就需要 對數據庫表進行更新了;對于這兩個操作,安卓給我們提供了SQLiteOpenHelper的兩個方法, onCreate( )與onUpgrade( )來實現
方法解析:
- onCreate(database):首次使用軟件時生成數據庫表
- onUpgrade(database,oldVersion,newVersion):在數據庫的版本發生變化時會被調用, 一般在軟件升級時才需改變版本號,而數據庫的版本是由程序員控制的,假設數據庫現在的 版本是1,由于業務的變更,修改了數據庫表結構,這時候就需要升級軟件,升級軟件時希望 更新用戶手機里的數據庫表結構,為了實現這一目的,可以把原來的數據庫版本設置為2 或者其他與舊版本號不同的數字即可!
代碼示例:
public class MyDBOpenHelper extends SQLiteOpenHelper {public MyDBOpenHelper(Context context, String name, CursorFactory factory,int version) {super(context, "randomItem.db", null, 1); }@Override//數據庫第一次創建時被調用public void onCreate(SQLiteDatabase db) {db.execSQL("CREATE TABLE person(personid INTEGER PRIMARY KEY AUTOINCREMENT,name VARCHAR(20))");}//軟件版本號發生改變時調用@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");} }代碼解析:
上述代碼第一次啟動應用,我們會創建這個my.db的文件,并且會執行onCreate()里的方法, 創建一個Person的表,他又兩個字段,主鍵personId和name字段;接著如我我們修改db的版本 號,那么下次啟動就會調用onUpgrade()里的方法,往表中再插入一個字段!另外這里是插入 一個字段,所以數據不會丟失,如果是重建表的話,表中的數據會全部丟失,后續會 來教大家如何解決這個問題!
流程小結:
- Step 1:自定義一個類繼承SQLiteOpenHelper類
- Step 2:在該類的構造方法的super中設置好要創建的數據庫名,版本號
- 重寫onCreate( )方法創建表結構
- 重寫onUpgrade( )方法定義版本號發生改變后執行的操作(如不需要,故此方法為空)
如何查看我們生成的db文件
當我們調用上面的MyDBOpenhelper的對象的getWritableDatabase()就會在下述目錄下創建我們的db 數據庫文件:
我們發現數據庫有兩個,前者是我們創建的數據庫,而后者則是為了能讓數據庫支持事務而產生的 臨時的日志文件!一般的大小是0字節! 而在File Explorer里我們確是打不開文件的,連txt都打不開,何況是.db! 所以下面給大家兩條路選:
- 1.先導出來,然后用SQLite的圖形化工具查看
- 2.配置adb環境變量后,通過adb shell來查看(命令行,裝比利器)!
方法1:使用SQLite圖形化工具查看db文件
我使用的是SQLite Expert Professional。
把我們的db文件導出到電腦桌面,打開SQLiteExpert
方法2:adb shell命令行帶你裝逼帶你飛
1.配置SDK環境變量:
右鍵我的電腦 ——> 高級系統設置 -> 環境變量 -> 新建系統變量 -> 把SDK的platform-tools路徑拷貝下: 比如筆者的:C:\Software\Coding\android-sdks-as\platform-tools
確定,然后再找到Path的環境變量,編輯,然后在結尾加上:%SDK_HOME%;
然后打開命令行,輸入adb,唰唰唰一堆東西,就說明配置成功了!
重點
在執行后續命令行指令之前,針對你的測試的機器可能有幾種:
- 1.原生模擬器:那行,你跳過這里,繼續往下
- 2.Genymotion模擬器:沒戲,Genymotion Shell執行不了下述命令
- 3.真機(已root):那么你打開File Explorer看看data/data/目錄下有東西沒?沒么? 下面提供一個方法,就是先裝個RE文件管理器,然后授予RE Root權限,接著來到根目錄: 然后長按data目錄,會彈出這樣的對話框:
接著等他慢慢修改權限,修改完畢后,我們再次打開DDMS的File Explorer,我們可以看到data/data里的東西了
2.進入adb shell,接著鍵入下述指令,來到我們app的databases目錄下:
接著依次輸入下述指令:
- sqlite3 my.db :打開數據庫文件
- .table 查看數據庫中有哪些表 接著你直接輸入數據庫語句就可以了,比如查詢:Select * from person
- .schema:查看建表語句
- .quit:退出數據庫的編輯
- .exit:退出設備控制臺
使用Android提供的API操作SQLite
public class MainActivity extends AppCompatActivity implements View.OnClickListener {private Context mContext;private Button btn_insert;private Button btn_query;private Button btn_update;private Button btn_delete;private SQLiteDatabase db;private MyDBOpenHelper myDBHelper;private StringBuilder sb;private int i = 1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mContext = MainActivity.this;myDBHelper = new MyDBOpenHelper(mContext, "my.db", null, 1);bindViews();}private void bindViews() {btn_insert = (Button) findViewById(R.id.btn_insert);btn_query = (Button) findViewById(R.id.btn_query);btn_update = (Button) findViewById(R.id.btn_update);btn_delete = (Button) findViewById(R.id.btn_delete);btn_query.setOnClickListener(this);btn_insert.setOnClickListener(this);btn_update.setOnClickListener(this);btn_delete.setOnClickListener(this);}@Overridepublic void onClick(View v) {db = myDBHelper.getWritableDatabase();switch (v.getId()) {case R.id.btn_insert:ContentValues values1 = new ContentValues();values1.put("name", "呵呵~" + i);i++;//參數依次是:表名,強行插入null值得數據列的列名,一行記錄的數據db.insert("person", null, values1);Toast.makeText(mContext, "插入完畢~", Toast.LENGTH_SHORT).show();break;case R.id.btn_query:sb = new StringBuilder();//參數依次是:表名,列名,where約束條件,where中占位符提供具體的值,指定group by的列,進一步約束//指定查詢結果的排序方式Cursor cursor = db.query("person", null, null, null, null, null, null);if (cursor.moveToFirst()) {do {int pid = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));sb.append("id:" + pid + ":" + name + "\n");} while (cursor.moveToNext());}cursor.close();Toast.makeText(mContext, sb.toString(), Toast.LENGTH_SHORT).show();break;case R.id.btn_update:ContentValues values2 = new ContentValues();values2.put("name", "嘻嘻~");//參數依次是表名,修改后的值,where條件,以及約束,如果不指定三四兩個參數,會更改所有行db.update("person", values2, "name = ?", new String[]{"呵呵~2"});break;case R.id.btn_delete://參數依次是表名,以及where條件與約束db.delete("person", "personid = ?", new String[]{"3"});break;}} }使用SQL語句操作數據庫
- execSQL(SQL,Object[]):使用帶占位符的SQL語句,這個是執行修改數據庫內容的sql語句用的
- rawQuery(SQL,Object[]):使用帶占位符的SQL查詢操作 另外前面忘了介紹下Curosr這個東西以及相關屬性,這里補充下: —— - - - - Cursor對象有點類似于JDBC中的ResultSet,結果集!使用差不多,提供一下方法移動查詢結果的記錄指針:
- move(offset):指定向上或者向下移動的行數,整數表示向下移動;負數表示向上移動!
- moveToFirst():指針移動到第一行,成功返回true,也說明有數據
- moveToLast():指針移動到最后一樣,成功返回true;
- moveToNext():指針移動到下一行,成功返回true,表明還有元素!
- moveToPrevious():移動到上一條記錄
- getCount( )獲得總得數據條數
- isFirst():是否為第一條記錄
- isLast():是否為最后一項
- moveToPosition(int):移動到指定行
1.插入數據:
public void save(Person p) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("INSERT INTO person(name,phone) values(?,?)",new String[]{p.getName(),p.getPhone()}); }2.刪除數據:
public void delete(Integer id) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("DELETE FROM person WHERE personid = ?",new String[]{id}); }3.修改數據:
public void update(Person p) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("UPDATE person SET name = ?,phone = ? WHERE personid = ?",new String[]{p.getName(),p.getPhone(),p.getId()}); }4.查詢數據:
public Person find(Integer id) {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person WHERE personid = ?",new String[]{id.toString()});//存在數據才返回trueif(cursor.moveToFirst()){int personid = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));return new Person(personid,name,phone);}cursor.close();return null; }5.數據分頁:
public List<Person> getScrollData(int offset,int maxResult) {List<Person> person = new ArrayList<Person>();SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person ORDER BY personid ASC LIMIT= ?,?",new String[]{String.valueOf(offset),String.valueOf(maxResult)});while(cursor.moveToNext()){int personid = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person.add(new Person(personid,name,phone)) ;}cursor.close();return person; }6.查詢記錄數:
public long getCount() {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT COUNT (*) FROM person",null);cursor.moveToFirst();long result = cursor.getLong(0);cursor.close();return result; }PS:除了上面獲取條數的方法外還可以使用cursor.getCount()方法獲得數據的條數, 但是SQL語句要改改!比如SELECT * FROM person;
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的数据存储之-SQLite数据库一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CoordinatorLayout与滚动
- 下一篇: 数据存储之-SQLite数据库二