Android資料存放區(七) SQLite使用注意和SQL語句

來源:互聯網
上載者:User

1、資料類型的問題

SQLite內部只支援NULL、INTEGER、REAL(浮點數)、TEXT(文本)和BLOB(大二進位對象)這5種資料類型,但實際上SQLite完全可以接受varchar(n)、char(n)、decimal(p,s)等資料類型,只不過SQLite會在原酸或儲存時將他們轉換為上面5種資料類型中相應的類型。

除此之外,SQLite還有一個特點:它允許把各種類型的資料儲存到任何類型欄位中,開發人員可以不用關心聲明該欄位所使用的資料類型。例如程式可以把字串類型的值存入到INTEGER類型的欄位中,也可以把數值資料類型的值存入到布爾類型的欄位中。。。。但是有一中情況例外:定義為INTEGER PRIMARY KEY的欄位只能儲存64位整數,當向這種欄位儲存除整數意外的其他類型的資料時,SQLite會產生錯誤。

並且,可以向字串欄位中插入任意長度的字串,即使聲明varchar(20)加以限制。

2、資料庫何時關閉問題

我們使用SQLiteOpenHelper擷取一個SQLiteDatabase資料庫物件,然後就可以去使用這個資料庫了。那麼這個資料庫何時關閉呢。一般我們不需要操作一次資料庫,就去關閉它,因為這樣很耗資源。畢竟這不是像J2EE上面的資料庫,J2EE伺服器上的資料庫會根據訪問的使用者產生許多資料庫連接,所以需要關閉。但是在Android手機上,只有我們當前的應用程式再回有一個資料庫的串連,當然不需要用一次關閉一次。

所以,我們只需要完成了所有的資料庫操作,或者退出程式的時候,選擇一個恰當的實際關閉。

3、SQLiteDatabase對象的擷取問題。

我們擷取資料庫執行個體時使用了getWritableDatabase()方法,也許朋友們會有疑問,在getWritableDatabase()和getReadableDatabase()中,你為什麼選擇前者作為整個應用的資料庫執行個體呢?在這裡我想和大家著重分析一下這一點。

我們來看一下SQLiteOpenHelper中的getReadableDatabase()方法:

    public synchronized SQLiteDatabase getReadableDatabase() {          if (mDatabase != null && mDatabase.isOpen()) {              // 如果發現mDatabase不為空白並且已經開啟則直接返回              return mDatabase;          }                if (mIsInitializing) {              // 如果正在初始化則拋出異常              throw new IllegalStateException("getReadableDatabase called recursively");          }                // 開始執行個體化資料庫mDatabase                try {              // 注意這裡是調用了getWritableDatabase()方法              return getWritableDatabase();          } catch (SQLiteException e) {              if (mName == null)                  throw e; // Can't open a temp database read-only!              Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e);          }                // 如果無法以可讀寫入模式開啟資料庫 則以唯讀方式開啟                SQLiteDatabase db = null;          try {              mIsInitializing = true;              String path = mContext.getDatabasePath(mName).getPath();// 擷取資料庫路徑              // 以唯讀方式開啟資料庫              db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);              if (db.getVersion() != mNewVersion) {                  throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to "                          + mNewVersion + ": " + path);              }                    onOpen(db);              Log.w(TAG, "Opened " + mName + " in read-only mode");              mDatabase = db;// 為mDatabase指定新開啟的資料庫              return mDatabase;// 返回開啟的資料庫          } finally {              mIsInitializing = false;              if (db != null && db != mDatabase)                  db.close();          }      }  

在getReadableDatabase()方法中,首先判斷是否已存在資料庫執行個體並且是開啟狀態,如果是,則直接返回該執行個體,否則試圖擷取一個可讀寫入模式的資料庫執行個體,如果遇到磁碟空間已滿等情況擷取失敗的話,再以唯讀模式開啟資料庫,擷取資料庫執行個體並返回,然後為mDatabase賦值為最新開啟的資料庫執行個體。既然有可能調用到getWritableDatabase()方法,我們就要看一下了:

    public synchronized SQLiteDatabase getWritableDatabase() {          if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {              // 如果mDatabase不為空白已開啟並且不是唯讀模式 則返回該執行個體              return mDatabase;          }                if (mIsInitializing) {              throw new IllegalStateException("getWritableDatabase called recursively");          }                // If we have a read-only database open, someone could be using it          // (though they shouldn't), which would cause a lock to be held on          // the file, and our attempts to open the database read-write would          // fail waiting for the file lock. To prevent that, we acquire the          // lock on the read-only database, which shuts out other users.                boolean success = false;          SQLiteDatabase db = null;          // 如果mDatabase不為空白則加鎖 阻止其他的操作          if (mDatabase != null)              mDatabase.lock();          try {              mIsInitializing = true;              if (mName == null) {                  db = SQLiteDatabase.create(null);              } else {                  // 開啟或建立資料庫                  db = mContext.openOrCreateDatabase(mName, 0, mFactory);              }              // 擷取資料庫版本(如果剛建立的資料庫,版本為0)              int version = db.getVersion();              // 比較版本(我們代碼中的版本mNewVersion為1)              if (version != mNewVersion) {                  db.beginTransaction();// 開始事務                  try {                      if (version == 0) {                          // 執行我們的onCreate方法                          onCreate(db);                      } else {                          // 如果我們應用升級了mNewVersion為2,而原版本為1則執行onUpgrade方法                          onUpgrade(db, version, mNewVersion);                      }                      db.setVersion(mNewVersion);// 設定最新版本                      db.setTransactionSuccessful();// 設定事務成功                  } finally {                      db.endTransaction();// 結束事務                  }              }                    onOpen(db);              success = true;              return db;// 返回可讀寫入模式的資料庫執行個體          } finally {              mIsInitializing = false;              if (success) {                  // 開啟成功                  if (mDatabase != null) {                      // 如果mDatabase有值則先關閉                      try {                          mDatabase.close();                      } catch (Exception e) {                      }                      mDatabase.unlock();// 解鎖                  }                  mDatabase = db;// 賦值給mDatabase              } else {                  // 開啟失敗的情況:解鎖、關閉                  if (mDatabase != null)                      mDatabase.unlock();                  if (db != null)                      db.close();              }          }      }  

大家可以看到,幾個關鍵步驟是,首先判斷mDatabase如果不為空白已開啟並不是唯讀模式則直接返回,否則如果mDatabase不為空白則加鎖,然後開始開啟或建立資料庫,比較版本,根據版本號碼來調用相應的方法,為資料庫設定新版本號碼,最後釋放舊的不為空白的mDatabase並解鎖,把新開啟的資料庫執行個體賦予mDatabase,並返回最新執行個體。

看完上面的過程之後,大家或許就清楚了許多,如果不是在遇到磁碟空間已滿等情況,getReadableDatabase()一般都會返回和getWritableDatabase()一樣的資料庫執行個體,所以我們在DBManager構造方法中使用getWritableDatabase()擷取整個應用所使用的資料庫執行個體是可行的。當然如果你真的擔心這種情況會發生,那麼你可以先用getWritableDatabase()擷取資料執行個體,如果遇到異常,再試圖用getReadableDatabase()擷取執行個體,當然這個時候你擷取的執行個體只能讀不能寫了。

並且,同一個資料庫只會返回一個SQLiteDatabase資料庫執行個體。

4、在Android中對資料庫動作陳述式和方法

SQLite中sql語句和MySql非常類似,完全可以去參照MySql的sql語句。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.