与其它数据库不同,SQLite的数据类型很简单,只有NULL(空类型)、INTEGER(整型)、REAL(浮点型)、TEXT(字符串型)、BLOB(二进制型)。
SQLite为动态数据类型(弱引用),当向数据库中插入某个值时,会检查该值的类型,若类型与插入列不匹配,SQLite会尝试将该值转换成相应类型。
学习SQLite的数据库操作需要对SQL有一定了解,若完全不了解,建议先看一下数据库的基础语法知识:
Android中提供了一个SQLiteOpenHelper类,使用该类可非常方便地进行数据库的创建与升级。
SQLiteHelper是一个抽象类,使用该类必须另外写一个类去继承自它,并实现两个关键的抽象方法onCreate()、onUpgrade(),这两个方法分别用于数据库的创建与升级。
SQLiteOpenHelper类中提供了两个构造函数可供重写,一般重写4个参数那个即可,其中第一个参数是context,第二个参数是数据库的名称,第三个参数允许在查询数据时返回一个自定义的Cursor,一般传入null,第四个参数是数据库版本号,用于数据库的升级操作。
在写好自定义的帮助类后,在活动类中进行实例化,再调用它的getReadableDtabase()或者getWritableDatabase()方法即可创建数据库。
另外,有不少人使用operOrCreateDatabase方法进行数据库的创建,如有兴趣,可前往这篇文章了解:Context与SQLiteDatabase的方法openOrCreateDatabase的区别 (context、SQLiteOpenHelper)
范例:
布局文件(本文后续例子中继续沿用此布局):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="15dp"
tools:context="com.studying.myapplication.MySQLiteActivity">
<Button
android:id="@+id/create_database"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="Create Database" />
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:text="Add Data" />
<Button
android:id="@+id/delete_data"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:text="Delete Data" />
<Button
android:id="@+id/update_data"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:text="Update Data" />
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:text="Query Data" />
</LinearLayout>
SQLiteOpenHelper实现类:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
//将建表语句定义为字符常量
public static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text)";
private Context mContext;
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//创建数据表
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
//用于升级数据库,请见下一例子
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
//实例化帮助类
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.create_database:
//创建或打开数据库
mHelper.getWritableDatabase();
break;
}
}
}
上面提到过,升级数据库(通常发生在app更高版本的覆盖安装)需要通过帮助类的onUpgrade()方法实现,而不能直接在onCreate()方法中直接执行修改语句。这是因为onCreate()方法尽在当前数据库未创建的情况下才会调用,若数据库已经存在,则不会再次调用该方法。此时,我们就需要通过onUpgrade()方法实现数据库的升级。
当实例化帮助类时传入的数据库版本号比上一次传入的大时,onUpgrade()方法就会被调用。因此,在升级数据库时,在onUpgrade()方法中写入改变的内容,而后在活动类中更改传入的版本号即可。
范例1:
在上面例子的基础上增加一张CATEGORY表。
自定义帮助类:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text)";
//升级测试用建表语句
public static final String CREATE_CATEGORY = "create table CATEGORY ("
+ "id integer primary key autoincrement, "
+ "category_name text,"
+ "category_code integer)";
private Context mContext;
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//如果用户当前是初次安装本程序,即数据库未被创建,则直接创建两个表
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
//若用户是覆盖安装,并且当前已创建的数据库版本为1,则仅创建CATEGORY表
db.execSQL(CREATE_CATEGORY);
default:
}
}
}
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
//活动类仅需在实例化时将版本号增大
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 2);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.create_database:
mHelper.getWritableDatabase();
break;
}
}
}
这里注意一个细节,onUpgrade()方法中的switch语句里的每一个分支都并没有break,这是为了保证在跨版本升级时能顺利依次完成中间的所有升级。例如从版本1直接升级到版本3时,就会依次进行2和3的升级。
范例2:
在范例1的基础上给BOOK表增加一个category_id字段。
帮助类:
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text, "
+ "category_id integer)";//增加一个字段
public static final String CREATE_CATEGORY = "create table CATEGORY ("
+ "id integer primary key autoincrement, "
+ "category_name text,"
+ "category_code integer)";
private Context mContext;
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
//如果用户当前是初次安装本程序,即数据库未被创建,则直接创建两个表
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//没有break,如果用户直接从第一版app升级到第三版app,则依次执行case 1和case 2。
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
case 2:
db.execSQL("alter table BOOK column category_id integer");
default:
}
}
}
上面已经学习了如何使用SQLiteOpenHelper类进行数据库的创建和升级,但是我们并没有使用到调用getReadableDatabase()或者getWritableDatabase()方法时返回的SQLiteDatabase对象,而这一对象,就是用来对数据进行“增删改查”操作的。
insert(String table, String nullColumnHack, ContentValues values)
table
:指定插入记录的表。
nullColumnHack
:若某些允许为空的列没有赋值,则自动赋值为null,传入null即可。
values
:ContentValues对象,相当于一个容器的作用,可通过它的put(key, values)方法(key为列名称,values为该列的值)将每一行的数据一一添加,而后再传入数据库。注意当插入多条记录时,每两次插入之间要调用clear()方法进行清空。
范例:
帮助类:(后面的删改查将沿用该帮助类)
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table BOOK ("
+ "id integer primary key autoincrement, "
+ "name text, "
+ "author text)";
private Context mContext;
public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
private SQLiteDatabase mDb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//省略创建数据库分支
case R.id.add_data:
//获取SQLiteDatabase对象
mDb = mHelper.getWritableDatabase();
//实例化ContentValues对象并进行数据组装
ContentValues values = new ContentValues();
values.put("name", "A");
values.put("author", "aa");
//插入数据
mDb.insert("BOOK", null, values);
//若需要插入多条记录,在这一步一定要调用values的clear()方法清空现有的数据
values.clear();
values.put("name", "B");
values.put("author", "bb");
mDb.insert("BOOK", null, values);
values.clear();
values.put("name", "C");
values.put("author", "cc");
mDb.insert("BOOK", null, values);
break;
}
}
}
delete(String table, String whereClause, String[] whereArgs)
whereClause
和whereArgs
:指定删除条件,若不指定则删除表中所有数据。相当于将一个条件语句拆分成两部分,第二个参数是用占位符替代了具体值的条件语句,第三个参数则是条件语句的值,例如将age > 30的记录删除,则第二个参数为"age > ?",第三个参数为new String[] {"30"}。
范例:
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
private SQLiteDatabase mDb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(this);
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//省略其它几个分支
case R.id.delete_data:
mDb = mHelper.getWritableDatabase();
//删除数据,?是一个占位符,第二、第三个参数合起来即删除id > 2的记录
mDb.delete("BOOK", "id > ?", new String[] {"2"});
break;
}
}
}
update(String table, ContentValues values, String whereClause, String[] whereArgs)
这里的四个参数相信大家已经很熟悉了,第一个为表名,第二个为ContentValues对象,装载更新数据,第三、第四个则为约束条件,指定更新的行,若不指定则更新全部行。
范例:
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
private SQLiteDatabase mDb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(this);
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(this);
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//省略其它几个分支
case R.id.update_data:
mDb = mHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//需要改哪一列数据就添加哪一列的,不一定要全部
values.put("name", "D");
mDb.update("BOOK", values, "id < ?", new String[] {"3"});
break;
}
}
}
query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
如果你学过SQL语言的话,相信对上面这一看起来非常复杂的参数列表是比较熟悉的,里面的参数基本上都可以与SQL中的select语句的修饰符对应上。调用query()方法会返回一个Cursor对象,里面含有所有查询结果。
table
:对应SQL中的from table_name
,指定查询的表名。
columns
:对应select column1, column2, ...
,指定查询的列名称。
selection
:对应where column = value
,指定查询的行的约束条件。
selectionArgs
:为selection重的占位符(?)提供具体值。
groupBy
:对应group by column
,指定对哪一列进行分组。
having
:对应having column = value
,进一步对分组后的结果进行约束。
orderBy
:对应order by column1, column2, ...
,指定查询结果的排序方式。
这里仅介绍最简单的查询,后面几个参数的使用可先前往了解SQL的语法:MySQL入门笔记(一)
范例:
活动类:
public class MySQLiteActivity extends Activity implements View.OnClickListener{
private MySQLiteOpenHelper mHelper;
private SQLiteDatabase mDb;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_sqlite);
mHelper = new MySQLiteOpenHelper(this, "BookStore.db", null, 1);
Button createDb = (Button) findViewById(R.id.create_database);
createDb.setOnClickListener(this);
Button addData = (Button) findViewById(R.id.add_data);
addData.setOnClickListener(this);
Button deleteData = (Button) findViewById(R.id.delete_data);
deleteData.setOnClickListener(this);
Button updateData = (Button) findViewById(R.id.update_data);
updateData.setOnClickListener(this);
Button queryData = (Button) findViewById(R.id.query_data);
queryData.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//省略其它几个分支
case R.id.query_data:
mDb = mHelper.getWritableDatabase();
//查询BOOK中所有数据
Cursor cursor = mDb.query("BOOK", null, null, null, null, null, null);
if (cursor.moveToFirst()) {
do {
//遍历cursor,取出数据
int id = cursor.getInt(cursor.getColumnIndex("id"));
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
//打印数据
Log.d("MySQLiteData", id + ". 《" + name + "》 " + author);
}while (cursor.moveToNext());
//关闭Cursor对象
cursor.close();
}
break;
}
}
}
SQLite是支持事务的,那么什么是事务呢?试想,假设有个数据表中的数据都很旧了,现在要将其全部替换成新的,就要先删除旧数据,而后再插入新数据。但是在过程中出现了异常,旧数据被删除之后,新数据没有成功插入,那这一个数据表的信息就全没了。而事务的特性就是保证某一个系列的操作,或者全部完成,或者全部不完成。也就是如果前面替换数据这一系列操作放在事务中进行,则要么数据替换成功,表内全部换成新数据,要么失败,保留旧数据,不会出现删了旧数据,但是没插入新数据的情况。
事务的使用方法比较简单,以下是Android中事务的标准用法:
//第一步,开启事务,db为SQLiteDatabase对象
db.beginTransaction();
try {
//在异常捕获的代码块中进行具体的操作
//在全部操作结束后将事务设置为成功
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally (
//结束事务
db.endTransaction();
)
下载说明
☉本站所有源码和资源均由站长亲自测试-绝对保证都可以架设,运营!
☉如源码和资源有损坏或所有链接均不能下载,请告知管理员,
☉本站软件和源码大部分为站长独资,资源购买和收集,放心下载!
☉唯一站长QQ:1004003180 [人格担保-本站注重诚信!]
☉购买建议E-mail:1004003180@qq.com 源码收购 E-mail:1004003180@qq.com
☉本站文件解压密码 【文章内都自带解压密码,每个密码不同!】