Android数据存储(七) SQLite使用注意和SQL语句
2012-08-27 21:22
741 查看
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()方法:
在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了:
大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。
看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了。
并且,同一个数据库只会返回一个SQLiteDatabase数据库实例。
4、在Android中对数据库操作语句和方法
SQLite中sql语句和MySql非常类似,完全可以去参照MySql的sql语句。
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语句。
相关文章推荐
- 野人学Android基础篇之数据存储第一课--SQLite的使用及注意点
- Android数据存储之SQLite中常用的SQL语句
- Android进阶#(5/12)独特高效的数据存储——SQLite数据库_SQLite中的SQL语句
- Android数据存储之SQLite使用
- Android demo-->学生选课系统,使用Sqlite存储数据
- 安卓开发SQlite使用执行SQL语句一些简单的处理——1.创建数据库,表和添加数据
- Android使用Sqlite存储数据用法示例
- Android复习练习八(SQLite使用SQL语句方式)
- Android SQLite数据库之一,使用sql语句操作SQLite数据库
- 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作
- android中常用的查询、插入、更新、删除等SQL语句以及SQLite数据类型
- android使用sqlite存储数据
- Android核心基础-5.Android 数据存储与访问-3.使用Sqlite进行数据存储
- Android数据存储之Sqlite的介绍及使用
- 使用Hive或Impala执行SQL语句,对存储在Elasticsearch中的数据操作(二)
- Android实例demo8之Sqlite的使用(sql语句、android api)
- android数据存储读取5:Sqlite一些要注意的地方
- Android数据存储SQLite-使用sql操作数据库
- Day07-Android中SQLite数据存储,ListView的基本使用
- Android数据存储之Sqlite的介绍及使用