㈠ 如何使用SQLite,Android上SQLite的最佳實踐

前些時候看到興趣小組里有人問「Android上SQLite的最佳實踐」是什麼,好奇地搜了一下,確實沒有一個好一點的指導文檔,平時的使用也只是簡單的拷貝code,並沒有深入的研究過。以下是我看到的Kevin關於其使用的心得,原文的大體的意思是:

Android例子涵蓋了一些Sqlite的基本用法,但它們並沒有深入地給出合理的使用方法,更重要的是,不合理的使用方法。大多數例子和文檔只是涉及最基本的資料庫查詢,或者教你如何創建一個ContentProvider。從來不提及的地方像:

· 什麼地方創建和保存SQLiteOpenHelper實例?

· 可以有多少個實例?

· 多線程同時訪問資料庫有沒有什麼要擔心的?

基本的內容是,你可以任意次數地連接Sqlite資料庫,而且Android系統也支持你這樣做。Sqlite擁有文件級別的鎖,用來同步訪問和防止錯誤。如果你只知道這些,那麼,將會給你帶來很大的痛苦。開源的一個好處是,你可以深入代碼一探究竟。從代碼和一些測試中,我了解到以下事實:

· Sqlite擁有文件級別的鎖。許多線程可以同時讀,但只有一個可以寫。鎖阻止多個同時寫入。

· Android在SQLiteDatabase中實現了一些java鎖來確保動作是同步進行。

· 如果你用多個線程瘋狂地訪問資料庫,你的資料庫不會(或不應該)崩潰。

沒提到的是,如果你通過多個不同的真實連接同時寫資料庫,其中的某個會失敗,它不會等到前一個完成後繼續寫入。簡單地,不會寫入你的改變,更糟糕的是,你也得不到一個異常,只是在LogCat中輸出一些message,僅此而已。

SQLiteOpenHelper類做了一些有趣的事。盡管它有方法可以獲得一個只讀的連接和可讀寫的連接,但實質上它們是同一個連接。假設沒有文件寫錯誤的話,只讀的連接實質上就是一個可讀寫的連接。有趣吧。因此,如果你的app中使用一個helper的話,即便從多線程中使用,你也從未使用多個連接。

同樣,一個helper中只有一個SQLiteDatabase的實例,這個實例中實現了一些java鎖。因此,當你正在執行資料庫的操作時,其它db的操作都將鎖定。即便是你使用多個線程來做這些事以便優化資料庫的性能,壞消息,沒有什麼用。

按照我的認識,SQLite工作的方式,基本上不可能會破壞你的資料庫,除非代碼里有bug或者有硬體問題。

因此,我推薦這樣使用:創建一個SQLiteOpenHelper靜態對象。什麼時候去close它呢?不需要。當app關閉,它會自動釋放文件引用。

但是,會不會有「close() was never explicitly called on database」異常呢?

如果你注意的話,當連接掛在那裡的時候,你沒有得到那個異常。你只是在連接已經建立,而你又嘗試打開另一個時才會有異常。因此,你只需要打開一次連接。

像這樣來使用:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper

{

private static DatabaseHelper instance;public static synchronized DatabaseHelper getHelper(Context context)

{

if (instance == null)

instance = new DatabaseHelper(context);return instance;

}

//Other stuff...

}

㈡ Android SQLite資料庫 的varchar大概能存多少中文字

SQLite的特性.
零配置 – 無需安裝和管理配置
儲存在單一磁碟文件中的一個完整的資料庫
資料庫文件可以在不同位元組順序的機器間自由的共享
支持資料庫大小至2TB
足夠小, 大致3萬行C代碼, 250K
比一些流行的資料庫在大部分普通資料庫操作要快
支持多種開發語言,C, PHP, Perl, Java, ASP .NET,Python

㈢ 如何打開android里的sqlite資料庫

描述詳細一點啊 大哥 你是想怎麼打開 在代碼中打開?還是adb打開查看資料庫?

  1. 代碼中的資料庫開發

    無非就是重寫 SqliteOpenHelper,然後獲取db類,通過增刪改查方法來操作資料庫,詳細步驟隨便一網路 都一大堆。

  2. 通過adb打開查看資料庫

    1. 連接設備

    2. adb shell

    3. su

    4. 進入db文件的文件夾

    5. sqlite3

    6. sql語句 進行查詢

㈣ android項目中如果有大量的數據並且面臨大量的用戶該怎麼存儲,sqlite能實現嗎

sqlite本身最大支持2TB的數據量,但是我不知道你說的面臨大量的用戶是什麼意思,因為一般意義上來講,android的apk程序一般都是作為一個客戶端的形式存在,所以資料庫實在伺服器端,客戶端請求數據即可,當然伺服器端的資料庫的管理要考慮很多問題,如數據同步,等。那當然資料庫文件在android本地也是可以的,那樣就是訪問效率會高一些,對SQLiteDatabase 對象的一些資料庫操作進行封裝即可,Android sdk中有一個DatabaseOpenHelper 類,你可以繼承他進行一些擴展,祝樓主開發順利,謝謝點贊。

㈤ android sqlite 對sqlite有哪些優化

關於 SQLite 的優化,首先是能用SQL語句的,就不要單筆操作,
Cursor 就更是能不用就不用。比如成批的
DELETE/UPDATE ,將條件組裝到
SQL 語句,會比使用 CURSOR
一條條的查再刪效率要高很多(
若干年前就曾使用存儲過程代替單筆操作,將一次批量計算時間從一晚上縮到了一小時以內
)。其次是對操作的優化:對於 INSERT/UPDATE
操作較多時使用事務,如果SELECT操作較多時,使用索引。

結合現在的工作,發現針對操作的優化,下面 這篇文章 可以翻譯出來歸檔。以下為正文:

SQLite 有一個簡潔的SQL介面,且以低內存佔用著稱。現如今,
SQLite 已經在 Android 及
iOS 開發中得到廣泛的應用。本文主要討論在 Android
應用如何優化 SQLite 的性能和資源佔用。

1, 使用事務( Transaction )

在默認情況下每一個SQL語句都被包一個全新的事務內,比如執行一個如INSERT這樣基本的資料庫操作,就會放到一個新創建的事務中執行。一次只需要操作一次資料庫操作時,讓SQLite自己來進行事務管理當然是明智的。但如果一次有大量的操作要做時,比如循環調用INSERT添加時,這樣就顯得開銷過大了,因為每一筆操作都要重新打開、寫入,最後再關閉journal文件,
這個文件是臨時用來保存數據操作的中間結果,詳細內容看這里( 參考 )。
如果明確地在一系列SQL語句前後以 BEGIN TRANSACTION 及
END TRANSACTION
這樣顯示地使用事務就可以避免上面的情況。對於那些不會改變數據的操作,這樣的方式也同樣可以提速(好似資料庫操作中單筆的操作效率將遠低於批次操作,如果用SQL語句可以搞定的事,就不可使用Cursor進行操作)。

註明:除了發起事務外,你必須還要負責對事務的提交和回滾操作。

在Android應用開發中可以使用類似如下的方式使用 BEGIN TRANSACTION
及 END TRANSACTION :
db.beginTransaction();
try{
for(int i =0; i< LENGTH ; i++,sequenceNum++)
{
// execute SQL
}
db.setTransactionSuccessful();// marks a commit
}
finally{
db.endTransaction();
}

2. 使用索引

如果沒有在資料庫使用索引,當你在一個沒有排序的數據表中使用映射查詢(projection
query)搜索時,無可避免的要執行一個全序列查找。這種情況通常並不是什麼問題,每種資料庫,包括SQLite都會為數據集執行索引來降低查找時間。

索引維護著一個表中某一列或某幾列的順序,這樣就可以快速定位到一組值,而不用掃遍全表。所有的索引信息會被保存在一個獨立的索引表中,所以會產生額外的空間佔用,不過絕對物超所值,特別是當你會在資料庫中進行大量的讀及搜索操作時。

SQLite會自動為每一個UNIQUE欄位創建索引,包括主鍵(Primary Key)欄位,另外也可以通過CREATE
INDEX進行顯示地創建。

注:如果你的查詢太復雜而無法使用所創建的索引,那你就要好好想想你資料庫的結構了。
3. 在Where分支中使用限定符

如果以字串拼接出SQL語句的Where,莫不如使用SQLite的query操作帶上'?'來編譯查詢。以下是它的好處:

a. 有利於SQLite緩存這些查詢。

b. 可以避免達到SQLite緩存的上限。使用字串拼接Where的查詢,每一個都被視為不同的查詢,這就容易達到緩存的上限。

c. 可以避免非法的SQL注入。
轉載

㈥ android sqlite 求sql語句查詢當天、本周、本月的數據~網上方法大部分都試了~無用!跪求大神指點!

$ sqlite3SQLite version 3.7.7 2011-06-23 19:49:22Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite>
sqlite> select datetime("now");2014-01-06 03:50:08sqlite> select datetime("now", "start of day");2014-01-06 00:00:00sqlite> select date('now','weekday 1');2014-01-06
sqlite> select datetime("now", "start of month");2014-01-01 00:00:00

㈦ android sqlite插入大量數據怎麼處理

使用事務。
dataBase.beginTransaction(); //手動設置開始事務
//數據插入操作循環
dataBase.setTransactionSuccessful(); //設置事務處理成功,不設置會自動回滾不提交
dataBase.endTransaction(); //處理完成

㈧ 如何確定android的資料庫最大規模和防止sqlitefullexception

安卓對SQLite表中的主鍵欄位要求比較苛刻,必須使用 _id 算是比較霸道吧。不過我們也沒辦法。。呵呵 你改改試一試, 我上次也是遇到這樣的問題,調了半天都沒解決。查API才發現的。希望能幫到你

㈨ Android開發 sqlite作用

SQLite簡介
Google為Andriod的較大的數據處理提供了SQLite,他在數據存儲、管理、維護等各方面都相當出色,功能也非常的強大。SQLite具備下列特點:

1.輕量級
使用 SQLite 只需要帶一個動態庫,就可以享受它的全部功能,而且那個動態庫的尺寸想當小。
2.獨立性
SQLite 資料庫的核心引擎不需要依賴第三方軟體,也不需要所謂的「安裝」。
3.隔離性
SQLite 資料庫中所有的信息(比如表、視圖、觸發器等)都包含在一個文件夾內,方便管理和維護。
4.跨平台
SQLite 目前支持大部分操作系統,不至電腦操作系統更在眾多的手機系統也是能夠運行,比如:Android。
5.多語言介面
SQLite 資料庫支持多語言編程介面。
6.安全性
SQLite 資料庫通過資料庫級上的獨占性和共享鎖來實現獨立事務處理。這意味著多個進程可以在同一時間從同一資料庫讀取數據,但只能有一個可以寫入數據。
Android中的SQLite使用
首先創建資料庫類

public class DatabaseHelper extends SQLiteOpenHelper {

private static final String DB_NAME = "mydata.db"; //資料庫名稱
private static final int version = 1; //資料庫版本

public DatabaseHelper(Context context) {
super(context, DB_NAME, null, version);
// TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table user(username varchar(20) not null , password varchar(60) not null );";
db.execSQL(sql);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub

}

}

SQLiteOpenHelper類介紹
SQLiteOpenHelper是SQLiteDatabase的一個幫助類,用來管理資料庫的創建和版本的更新。一般是建立一個類繼承它,並實現它的onCreate和onUpgrade方法。

方法名
方法描述

SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version) 構造方法,一般是傳遞一個要創建的資料庫名稱那麼參數
onCreate(SQLiteDatabase db) 創建資料庫時調用
onUpgrade(SQLiteDatabase db,int oldVersion , int newVersion) 版本更新時調用
getReadableDatabase() 創建或打開一個只讀資料庫
getWritableDatabase() 創建或打開一個讀寫資料庫
下面來介紹調用的方法
創建資料庫
這里特別的地方是通過調用了SQLiteOpenHelper類的getReadableDatabase()方法來實現創建一個資料庫的

1
2
3

DatabaseHelper database = new DatabaseHelper(this);//這段代碼放到Activity類中才用this
SQLiteDatabase db = null;
db = database.getReadalbeDatabase();

SQLiteDatabase類為我們提供了很多種方法,而較常用的方法如下

(返回值)方法名
方法描述

(int) delete(String table,String whereClause,String[] whereArgs) 刪除數據行的便捷方法
(long) insert(String table,String nullColumnHack,ContentValues values) 添加數據行的便捷方法
(int) update(String table, ContentValues values, String whereClause, String[] whereArgs) 更新數據行的便捷方法
(void) execSQL(String sql) 執行一個SQL語句,可以是一個select或其他的sql語句
(void) close() 關閉資料庫
(Cursor) query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit) 查詢指定的數據表返回一個帶游標的數據集
(Cursor) rawQuery(String sql, String[] selectionArgs) 運行一個預置的SQL語句,返回帶游標的數據集(與上面的語句最大的區別就是防止SQL注入)
數據的添刪改查分別可以通過2種途徑來實現
數據的添加
1.使用insert方法

1
2
3

ContentValues cv = new ContentValues();//實例化一個ContentValues用來裝載待插入的數據cv.put("username","Jack Johnson");//添加用戶名
cv.put("password","iLovePopMusic"); //添加密碼
db.insert("user",null,cv);//執行插入操作

2.使用execSQL方式來實現

1
2

String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL語句
db.execSQL(sql);//執行SQL語句

數據的刪除
同樣有2種方式可以實現

1
2
3

String whereClause = "username=?";//刪除的條件
String[] whereArgs = {"Jack Johnson"};//刪除的條件參數
db.delete("user",whereClause,whereArgs);//執行刪除

使用execSQL方式的實現

1
2

String sql = "delete from user where username='Jack Johnson'";//刪除操作的SQL語句
db.execSQL(sql);//執行刪除操作

數據修改
同上,仍是2種方式

1
2
3
4
5

ContentValues cv = new ContentValues();//實例化ContentValues
cv.put("password","iHatePopMusic");//添加要更改的欄位及內容
String whereClause = "username=?";//修改條件
String[] whereArgs = {"Jack Johnson"};//修改條件的參數
db.update("user",cv,whereClause,whereArgs);//執行修改

使用execSQL方式的實現

1
2

String sql = "update [user] set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL語句
db.execSQL(sql);//執行修改

數據查詢
數據查詢相對前面幾種方法就復雜一些了,因為查詢會帶有很多條件
通過query實現查詢的
public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit)
各參數說明:
table:表名稱
colums:列名稱數組
selection:條件子句,相當於where
selectionArgs:條件語句的參數數組
groupBy:分組
having:分組條件
orderBy:排序類
limit:分頁查詢的限制
Cursor:返回值,相當於結果集ResultSet
針對游標(Cursor)也提供了不少方法

方法名稱
方法描述

getCount() 總記錄條數
isFirst() 判斷是否第一條記錄
isLast() 判斷是否最後一條記錄
moveToFirst() 移動到第一條記錄
moveToLast() 移動到最後一條記錄
move(int offset) 移動到指定的記錄
moveToNext() 移動到嚇一條記錄
moveToPrevious() 移動到上一條記錄
getColumnIndex(String columnName) 獲得指定列索引的int類型值
實現代碼

1
2
3
4
5
6
7
8

Cursor c = db.query("user",null,null,null,null,null,null);//查詢並獲得游標
if(c.moveToFirst()){//判斷游標是否為空
for(int i=0;i<c.getCount();i++){
c.move(i);//移動到指定記錄
String username = c.getString(c.getColumnIndex("username");
String password = c.getString(c.getColumnIndex("password"));
}
}

通過rawQuery實現的帶參數查詢

1
2
3
4

Cursor c = db.rawQuery("select * from user where username=?",new Stirng[]{"Jack Johnson"});
if(cursor.moveToFirst()) {
String password = c.getString(c.getColumnIndex("password"));
}

㈩ android手機上sqllite插入數據的性能是多少

SQLite 因其小巧輕便被安卓系統廣泛採用,當然在操作小數據量時,差異並不明顯;但當 SQLite 在操作略大一點的數據時就顯得力不存心了,這時的 CRUD 操作對移動存儲設備的性能有著極大的要求,另外用戶體驗的良好性也對 SQLite 的性能優化提出了要求。那麼,當我們在操作大數據量時如何對 SQLite 進行優化呢?正確的操作是:開啟事務。下面我們通過採用不同的方式向資料庫中插入 10000 條數據來進行比較以體現開啟事務對 SQLite 性能提升方面所做出的貢獻。首先看一張截圖來進行一個感性的認識:

源碼及安裝文件下載方式一:SQLiteDataBase.zip
從上圖中我們會很清晰的看到通過普通方式插入 10000 條數據和開啟事務插入 10000 條數據之間的差異,整整差了 83 秒。下面我們來看測試代碼:

package cn.sunzn.sqlitedatabase;

import android.app.Activity;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;

public class MainActivity extends Activity {

protected static final int SUCCESS_INSERT_TO_DB_ONE = 1;
protected static final int SUCCESS_INSERT_TO_DB_TWO = 2;
private EditText et_usedtime1;
private EditText et_usedtime2;
Handler handler = new Handler() {

public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SUCCESS_INSERT_TO_DB_ONE:
Integer usetime_one = (Integer) msg.obj;
et_usedtime1.setText("插入10000條數據耗時:" + usetime_one / 1000 + "秒");
break;
case SUCCESS_INSERT_TO_DB_TWO:
Integer usetime_two = (Integer) msg.obj;
et_usedtime2.setText("插入10000條數據耗時:" + usetime_two / 1000 + "秒");
break;
default:
break;
}
}
};

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

et_usedtime1 = (EditText) findViewById(R.id.et_usedtime1);
et_usedtime2 = (EditText) findViewById(R.id.et_usedtime2);
}

/**
* 1. 普通方式插入資料庫 10000 條數據
*/
public void insert1(View view) {
MySQLiteOpenHelper openHelper = new MySQLiteOpenHelper(getApplicationContext());
final SQLiteDatabase database = openHelper.getWritableDatabase();
if (database.isOpen()) {
new Thread() {
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
ContentValues values = new ContentValues();
values.put("name", "tom:" + i);
database.insert("person", "_id", values);
}
database.close();
long end = System.currentTimeMillis();
int usetime_one = (int) (end - start);
Message message = new Message();
message.what = SUCCESS_INSERT_TO_DB_ONE;
message.obj = usetime_one;
handler.sendMessage(message);
};
}.start();
}
}

/**
* 2. 開啟事務插入資料庫 10000 條數據
*/
public void insert2(View view) {
MySQLiteOpenHelper openHelper = new MySQLiteOpenHelper(getApplicationContext());
final SQLiteDatabase database = openHelper.getWritableDatabase();
if (database.isOpen()) {
new Thread() {
public void run() {
long start = System.currentTimeMillis();
database.beginTransaction();
for (int i = 0; i < 10000; i++) {
ContentValues values = new ContentValues();
values.put("name", "tom:" + i);
database.insert("person", "_id", values);
}
database.setTransactionSuccessful();
database.endTransaction();
database.close();
long end = System.currentTimeMillis();
int usetime_two = (int) (end - start);
Message message = new Message();
message.what = SUCCESS_INSERT_TO_DB_TWO;
message.obj = usetime_two;
handler.sendMessage(message);
};
}.start();
}
}

public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}

為什麼只是開啟了一個事務就會有這么大的差距呢?很簡單,SQLite 預設為每個操作開啟了一個事務,那麼測試代碼循環插入 10000 次開啟了 10000 個事務,"事務開啟 + SQL 執行 + 事務關閉" 自然耗費了大量的時間,這也是後面顯式開啟事務後為什麼如此快的原因。