1. 程式人生 > 實用技巧 >android sqlite 資料型別

android sqlite 資料型別

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

android中的應用開發很難避免不去使用資料庫,這次就和大家聊聊android中的資料庫操作。

一、android內的資料庫的基礎知識介紹

1.用了什麼資料庫


android中採用的資料庫是SQLite這個輕量級的嵌入式開源資料庫,它是用c語言構建的。相關簡介可以從連結檢視。

2.資料庫基本知識觀花


對於一些和我一樣還沒有真正系統學習資料庫技術的同學來說,把SQL92標準中的一些基本概念、基本語句快速的瞭解一下,是很有必要的,這樣待會用Android的database相關方法去執行一些資料庫語句時就不會茫然了。

資料庫的基本結構——表格

表格是資料庫中儲存資料的基本架構。表格被分為欄位 (column) 及列位 (row)。每一列代表一筆資料,而每一欄代表一筆資料的一部份。舉例來說,如果我們有一個記載顧客資料的表格,那欄位就有可能包括姓、名、地址、城市、國家、生日...等等。每一個表格擁有一個獨一無二的名字(Table Name)以便能夠讓使用者定位到它上面。一個典型的表格結構如下:

Store_Information 表格

store_name Sales Date

Los Angeles $1500 Jan-05-1999

San Diego $250 Jan-07-1999

Los Angeles

$300 Jan-08-1999

Boston $700 Jan-08-1999

該表格的表格名字為Store_Information,一共有三個欄位,分別為store_name , Sales , Data ,已經錄入了四筆資料所以有四個列位。

②關於資料型別

和其他的資料庫不同的是,sqlite是無型別的。也就是當你建立一個表格時,無需對每一個欄位要儲存的資料的型別進行宣告,當你在給表格增加資料條目時,sqlite會自動找到存入的資料的型別。

SQLite允許忽略資料型別,但是,仍然建議在Create Table語句中指定資料型別,因為資料型別有利於增強程式的可讀性。SQLite支援常見的資料型別,如VARCHAR、NVARCHAR、TEXT、 INTEGER、FLOAT、BOOLEAN、CLOB、BLOB、TIMESTAMP、NUMERIC、VARYING、CHARACTER、 NATl0NAI, VARYINGCHARACTER。這些資料型別都是SQL92標準中規定的標準資料庫資料型別,想要有更近一步瞭解,請參看下表。

你或許已經在納悶了,為什麼之前的資料型別是大寫的,而到了這個表格就變成了小寫的。其實這是sqlite的一個不得不提的特性:sqlite是大小寫不敏感的!這一特性對於很多c語言fans來說是很不習慣的。

③資料庫的基本操作語句


其實這個還是SQL92標準中的一部分,只是不同的資料庫會有一點點的不同而已,下面就對在android中最常用的幾個操作語句給以概述,詳細介紹請參看SQL語句簡單介紹。

(1)CREATE TABLE

由於建立一個表格,基本使用語法結構是:

CREATE TABLE "表格名" ("欄位1" 儲存資料型別 , "欄位3" 儲存資料型別 , "欄位2" 儲存資料型別 .....);

例如我要建立剛才的Store_Information表格,就可以這樣:

CREATE TABLE Store_Information (Store_Name char[50] , Sales long , Date date );

需要提示的是,這裡還是聲明瞭資料型別。而且不難發現,c語言構建的sqlite自身也有一些c語言的性格(例如一個完整語句後的分號)。

(2)SELECT

用於將資料從資料庫中的表格內選出,基本語法結構為:

SELECT "欄位名" FROM "表格名" ;

例如我想將 Store_Information 裡面的store_name 選出,則可以這樣:

SELECT store_name FROM Store_Information ;

這句執行後就會顯示如下的資訊:

store_name

Los Angeles

San Diego

Los Angeles

Boston

好了,效果一目瞭然。

(3)SELECT語句可以新增條件來縮小選擇結果:

去掉重複的結果:

SELECT DISTINCT "欄位名" FROM "表格名"

例如將剛才的語句改為:

SELECT DISTINCT store_name FROM Store_Information ;

則顯示的結果為:


store_name

Los Angeles

San Diego

Boston

實現有條件的篩選:

SELECT "欄位名" FROM "表格名" WHERE "條件語句" ;

條件語句和c語言中的類似,只不過用AND表示“且”,OR表示“或”。

例如對錶執行如下語句:

SELECT store_name FROM Store_Information WHERE Sales > 1000 ;

則顯示結果為:

store_name

Los Angeles

其中WHERE語句用的較多,因為它可以實現自定義條件的使用和多條件的組合。

(4)INSERT INTO

在表格中加入資料——可以實現一筆的加入和多筆的加入。

加入一筆:

INSERT INTO "表格名" ("欄位1", "欄位2", ...) VALUES ("值1", "值2", ...);


加入多筆:

INSERT INTO "待加入資料的表格" ("欄位1", "欄位2", ...) SELECT "欄位3", "欄位4", ... FROM "被加入的表格" ;

加入多筆其實就是將另一個表格加入到現有表格中。

(5)UPDATE

用於修改表格中的資料,語法結構為:

UPDATE "表格名" SET "欄位1" = [新值] WHERE {條件};

例如:

UPDATE Store_Information SET Sales = 500 WHERE store_name = "Los Angeles" AND Date = "Jan-08-1999" ;

具體是什麼意思的話就不說了,你懂的~~~

(6)DELETE FROM

刪除表格中的某些資料,語法結構為:

DELETE FROM "表格名" WHERE {條件} ;

滿足條件的所有資料都會被刪除掉。

二、如何在android中呼叫資料庫資源


在android中主要有兩種方法來實現對資料庫的訪問,一種是adb shell方式,另一種是通過相關的android 的java類來間接的對資料庫來進行操作。其中前者主要用於在開發過程中進行除錯等工作,後者則為android中主要的使用資料庫的方式。

下面就對這兩種方式進行一個簡要的介紹。

1.adb shell方式

說白了,adb shell 就是一個android模擬器的後臺資源呼叫器(個人理解啦~~)。它的操作方式和命令提示符差不多——以命令列的方式進行。

既然是模擬器的後臺資源呼叫器,那當然得先開啟android模擬器了。

開啟模擬器後,再開啟命令提示符,在裡面輸入adb shell,這時會出現一個#號(懂linux的同學懂的),具體效果如下:

然後你就可以像在linux下進行shell命令的執行了。

接著輸入 cd data/data/ 並執行,再執行ls,則會顯示一些安裝的軟體的工程包名,效果如下:

其實這在模擬器中是以一個個資料夾的形式存在的,所以你可以用cd命令進入它。例如我進入一個後,再用ls命令顯示裡面的內容:

該資料夾內又存在databases、 lib等資料夾(如果沒有databases的話可以自己手動用mkdir命令建立一個)。而這個databases資料夾就是這個應用的資料庫檔案的所在地,cd進入後,應該會看到裡面有一個或多個.db格式的檔案(其實sqlite對檔案的名字沒有特殊要求,你用.txt等其他的格式也可以,但推薦.db)。如果沒有db檔案的話,可以用如下命令建立:sqlite3 mydata.db。這樣就會在databases裡面生成了一個數據庫檔案。如果已存在,可以直接用sqlite3命令呼叫該資料庫檔案,命令為 sqlite3 mydata.db(其實就是和剛才的命令一個樣)。接下來你就會看到:

在sqlite>後面就可以執行你的sql語句了。下面執行了一些簡單的語句:

好了,adb shell的方式介紹到這裡。

2.通過android中的相關java類

Android中對資料庫進行操作的相關的藉口、類等都在andorid.database和android.database.sqlite兩個包裡面。裡面存在著很多的與資料庫操作相關的類,但是在平時普通的開發中最經常遇到的僅僅就是那幾個類而已,所以在這裡我就省去通篇的介紹,對一些常用的介面、類做一下簡介。

SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

文件資訊:

public class

SQLiteDatabase

Exposes methods to manage a SQLite database.SQLiteDatabase has methods tocreate, delete, execute SQLcommands, and perform other common database management tasks.atabase names must be unique within an application, not across all applications.

簡介:

這個是在android中資料庫操作使用最頻繁的一個類。通過它可以實現資料庫的建立或開啟、建立表、插入資料、刪除資料、查詢資料、修改資料等操作。

重要方法介紹:

(1)public staticSQLiteDatabaseopenOrCreateDatabase(Filefile,SQLiteDatabase.CursorFactoryfactory)

public staticSQLiteDatabaseopenOrCreateDatabase(Stringpath,SQLiteDatabase.CursorFactoryfactory)

這個方法用於開啟或建立一個數據庫(對於sqlite來說,就是開啟或產生一個數據庫檔案),引數中的File類就是java中表示系統檔案路徑的File類,而SQLiteDatabase.CursorFactory則是一個產生Cursor物件的工廠類(Cursor介面將在後面介紹到)。


(2)publiclonginsert(Stringtable,StringnullColumnHack,ContentValuesvalues)

看到它的名字以及sql中的相關語句你不難猜到這個方法用於在資料庫中加入資料。ContentValue類似於java中HashMap類,用於以鍵值對的方式儲存資料。


(3)publicintdelete(Stringtable,StringwhereClause,String[]whereArgs)

不用說了,用於刪除表中的資料。


(4)publicCursorquery(booleandistinct,Stringtable,String[]columns,Stringselection,String[]selectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit)

名字很長是吧,它的功能也很強大,用於查詢資料庫中的資料。


(5)publicintupdate(Stringtable,ContentValuesvalues,StringwhereClause,String[]whereArgs)

用於修改資料。根據傳入引數的名字可以對使用方法略知一二。


(6)publicvoidexecSQL(Stringsql,Object[]bindArgs)

publicvoidexecSQL(Stringsql)

這是我個人認為最為重要的方法。這個方法用於執行你用String表示的非查詢(因為它不會返回一個Cursor物件)的sql語句,例如CREATE,SELECT等。遺憾的是現在尚無法一次呼叫該方法來執行用“;”分開的多條sql語句。第二個重寫方法使用的更多些。

另外在此提問:第一個重寫方法中bindArgs表示的是一些什麼,用來做什麼用,知道的同學可以告訴我下,謝謝!


(7)publicvoidclose()

用來關閉資料庫並釋放資料庫佔用的相關資源。


SQLiteOpenHelper (android.database.sqlite.SQLiteOpenHelper)

文件資訊:

publicabstractclass

SQLiteOpenHelper

A helper class to manage database creation and version management. You create a subclass implementingonCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int)and optionallyonOpen(SQLiteDatabase), and this class takes care of opening the database if it exists, creating it if it does not, and upgrading it as necessary. Transactions are used to make sure the database is always in a sensible state.

簡介:

正如它的名字所表述的一樣,這個抽象類是一個輔助類(Helper),用來開啟(若資料庫已存在)或建立資料庫的。關於抽象類我們都知道,如果要使用它,一定是繼承它。所以使用它都是通過自己定義一個類繼承於它,並實現onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int),onOpen(SQLiteDatabase)三個方法。

在我看來,所謂的輔助類,其實就是充當了一個封裝器——也就是說用於對其輔助的類實現一個java上的封裝。在這裡,SQLiteOpenHelper就是用來對SQLiteDatabase進行一個封裝處理。初學的同學想要進一步理解的話可以先看看什麼是封裝

它包含的方法如下:

(1)synchronizedvoidclose()

關閉任何已開啟的資料庫物件。

(2)synchronizedSQLiteDatabasegetReadableDatabase()

建立或開啟一個僅僅可讀的(read-only)資料庫。

(3)synchronizedSQLiteDatabasegetWritableDatabase()

建立或開啟一個可讀可寫的資料庫。

(4)abstractvoidonCreate(SQLiteDatabasedb)

當資料庫被第一次建立時被呼叫的的方法(類似於Activity的onCreate())。

(5)voidonOpen(SQLiteDatabasedb)

資料庫已經被成開啟後被呼叫。

(6)abstractvoidonUpgrade(SQLiteDatabasedb, intoldVersion, intnewVersion)

當資料庫需要被更改(更新)時被呼叫。

Cursor(android.database.Cursor)

文件資訊:

public interface

Cursor

This interface provides random read-write access to the result set returned by a database query.

簡介:

Cursor沒有構造方法,只能通過query方法獲得。

前面提到了,execSQL方法無法執行與查詢相關的sql語句,是因為無法返回一個Cursor物件——查詢需要將查到的結果(就是表中的哪一行滿足查詢條件)返回,execSQL是返回void的,所以無法操作查詢語句。從這裡可以瞭解到,Cursor介面從某種意義上說就是為了彌補這一點的——query方法就是返回了一個Cursor物件。從名字上看,它的意思是遊標,所以大概可以猜到他起到了一個指代的作用(事實上就是的,它指代資料庫中儲存資料的表的一行,並且還可以簡單的處理該行資料項的資訊)。從類的描述看,Cursor提供了對一個數據庫查詢動作返回結果束的隨機讀寫途徑,也就是說,它是一個對查詢操作返回結果進行進一步處理的類,而這些處理就是用Cursor裡的方法實現的。

結合SimpleCursorAdapter這個介面卡類,你可以很方便的將資料庫中的資料顯示到AdapterView(例如ListView,GridView)中——這也是Cursor的另一大用處。

如果你瞭解java中的迭代器(Iterator)的話你就會發現其實Cursor和迭代器有些相似,這樣你可能會更快的瞭解Cursor

一些常用的方法有:

(1)public abstractbooleanmoveToPosition(intposition)

public abstractbooleanmoveToFirst()

public abstractbooleanmoveToLast()

public abstractbooleanmoveToNext()

public abstractbooleanmoveToPrevious()

把這些方法放在一起的目的很明顯:它們都是對Cursor指向的位置進行操作的方法——移到某個指定的位置、移到第一行、移到最後一行、移向下一行、移向上一行等等。

(2)public abstractintgetCount()

返回Cursor指向的表含有的總資料項數。

(3)public abstractbooleanrequery()

Cursor是被一個query方法產生的,而這個方法就是將那個query方法所做的查詢動作再執行一遍——這將會改變呼叫該方法的Cursor物件的值,也就是說,Cursor使用了該方法後就復位了。

(4)public abstractbooleanisClosed()

public abstractbooleanisFirst()

public abstractbooleanisLast()

public abstractbooleanisNull(intcolumnIndex)

public abstractbooleanisClosed()

public abstractbooleanisAfterLast()

public abstractbooleanisBeforeFirst()

在java中,類似於isWhatever形式的方法大都是對物件狀態進行判斷的方法——Whatever成立則返回true,不成立則返回false。這些方法也不例外。

值得提一下的是isNull方法,該方法測試某個欄位所儲存的資訊是否為NULL。引數columnIndex代表了那個欄位的代號。

④另外建議各位瞭解一下SimpleCursorAdapter(android.widget.SimpleCursorAdapter)這個介面卡類。

好了,介紹這麼多了,該上原始碼了。這個原始碼很簡單,但代表一種使用模式,所以還是值得仔細研究的。

1.實現一個繼承SQLiteOpenHelper的類

  1. importandroid.content.ContentValues;

  2. importandroid.content.Context;

  3. importandroid.database.Cursor;

  4. importandroid.database.sqlite.SQLiteDatabase;

  5. importandroid.database.sqlite.SQLiteOpenHelper;

  6. publicclassDBHelperextendsSQLiteOpenHelper{

  7. privatestaticfinalStringDB_NAME="coll.db";

  8. privatestaticfinalStringTBL_NAME="CollTbl";

  9. privatestaticfinalStringCREATE_TBL="createtable"

  10. +"CollTbl(_idintegerprimarykeyautoincrement,nametext,urltext,desctext)";

  11. privateSQLiteDatabasedb;

  12. DBHelper(Contextc){

  13. super(c,DB_NAME,null,2);

  14. }

  15. @Override

  16. publicvoidonCreate(SQLiteDatabasedb){

  17. this.db=db;

  18. db.execSQL(CREATE_TBL);

  19. }

  20. publicvoidinsert(ContentValuesvalues){

  21. SQLiteDatabasedb=getWritableDatabase();

  22. db.insert(TBL_NAME,null,values);

  23. db.close();

  24. }

  25. publicCursorquery(){

  26. SQLiteDatabasedb=getWritableDatabase();

  27. Cursorc=db.query(TBL_NAME,null,null,null,null,null,null);

  28. returnc;

  29. }

  30. publicvoiddel(intid){

  31. if(db==null)

  32. db=getWritableDatabase();

  33. db.delete(TBL_NAME,"_id=?",newString[]{String.valueOf(id)});

  34. }

  35. publicvoidclose(){

  36. if(db!=null)

  37. db.close();

  38. }

  39. @Override

  40. publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){

  41. }

  42. }

2.建立一個錄入資料的類

  1. importandroid.app.Activity;

  2. importandroid.content.ContentValues;

  3. importandroid.content.Intent;

  4. importandroid.os.Bundle;

  5. importandroid.view.View;

  6. importandroid.view.View.OnClickListener;

  7. importandroid.widget.Button;

  8. importandroid.widget.EditText;

  9. publicclassAddActivityextendsActivity{

  10. privateEditTextet1,et2,et3;

  11. privateButtonb1;

  12. @Override

  13. publicvoidonCreate(BundlesavedInstanceState){

  14. super.onCreate(savedInstanceState);

  15. setContentView(R.layout.add);

  16. this.setTitle("新增收藏資訊");

  17. et1=(EditText)findViewById(R.id.EditTextName);

  18. et2=(EditText)findViewById(R.id.EditTextUrl);

  19. et3=(EditText)findViewById(R.id.EditTextDesc);

  20. b1=(Button)findViewById(R.id.ButtonAdd);

  21. b1.setOnClickListener(newOnClickListener(){

  22. publicvoidonClick(Viewv){

  23. Stringname=et1.getText().toString();

  24. Stringurl=et2.getText().toString();

  25. Stringdesc=et3.getText().toString();

  26. ContentValuesvalues=newContentValues();

  27. values.put("name",name);

  28. values.put("url",url);

  29. values.put("desc",desc);

  30. DBHelperhelper=newDBHelper(getApplicationContext());

  31. helper.insert(values);

  32. Intentintent=newIntent(AddActivity.this,

  33. QueryActivity.class);

  34. startActivity(intent);

  35. }

  36. });

  37. }

  38. }

3.建立一個顯示資料庫資料的類


  1. importandroid.app.AlertDialog;

  2. importandroid.app.ListActivity;

  3. importandroid.content.DialogInterface;

  4. importandroid.database.Cursor;

  5. importandroid.os.Bundle;

  6. importandroid.view.View;

  7. importandroid.widget.AdapterView;

  8. importandroid.widget.ListView;

  9. importandroid.widget.SimpleCursorAdapter;

  10. importandroid.widget.AdapterView.OnItemClickListener;

  11. publicclassQueryActivityextendsListActivity{

  12. @Override

  13. publicvoidonCreate(BundlesavedInstanceState){

  14. super.onCreate(savedInstanceState);

  15. this.setTitle("瀏覽收藏資訊");

  16. finalDBHelperhelpter=newDBHelper(this);

  17. Cursorc=helpter.query();

  18. String[]from={"_id","name","url","desc"};

  19. int[]to={R.id.text0,R.id.text1,R.id.text2,R.id.text3};

  20. SimpleCursorAdapteradapter=newSimpleCursorAdapter(this,

  21. R.layout.row,c,from,to);

  22. ListViewlistView=getListView();

  23. listView.setAdapter(adapter);

  24. finalAlertDialog.Builderbuilder=newAlertDialog.Builder(this);

  25. listView.setOnItemClickListener(newOnItemClickListener(){

  26. @Override

  27. publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,

  28. longarg3){

  29. finallongtemp=arg3;

  30. builder.setMessage("真的要刪除該記錄嗎?").setPositiveButton("是",

  31. newDialogInterface.OnClickListener(){

  32. publicvoidonClick(DialogInterfacedialog,

  33. intwhich){

  34. helpter.del((int)temp);

  35. Cursorc=helpter.query();

  36. String[]from={"_id","name","url","desc"};

  37. int[]to={R.id.text0,R.id.text1,R.id.text2,R.id.text3};

  38. SimpleCursorAdapteradapter=newSimpleCursorAdapter(getApplicationContext(),

  39. R.layout.row,c,from,to);

  40. ListViewlistView=getListView();

  41. listView.setAdapter(adapter);

  42. }

  43. }).setNegativeButton("否",

  44. newDialogInterface.OnClickListener(){

  45. publicvoidonClick(DialogInterfacedialog,

  46. intwhich){

  47. }

  48. });

  49. AlertDialogad=builder.create();

  50. ad.show();

  51. }

  52. });

  53. helpter.close();

  54. }

  55. }






轉載於:https://my.oschina.net/airship/blog/366337