通过一个简单的例子来学习Sqlite,学生选课系统,一开始的需求是学生可以选课,选课完成后可以查询到已经选择的课。

首先设计三个表,学生,课程,选课。学生表存储学生的信息,课程表存储课程的信息,选课表存储学生已经选择的课程。建表的语句可以通过SQLite Expert这个软件来测试。

在Sqlite Expert中新建一个数据库

切换到SQL标签

分别执行如下语句

create table if not exists Students(id integer primary key, name text not null)
create table if not exists Subjects(id integer primary key, name text not null)
create table if not exists Subject_Select(id integer primary key unique, student_id integer references Students(id), subject_id integer references Subjects(id), unique_check text unique not null)

成功创建了3个表,说明SQL语句没有错误

接下来使用代码来创建数据库

public class TestSqlite {

    private static TestSqlite mInstance;

    public static TestSqlite Instance() {
        return TestSqlite.mInstance;
    }

    private final SQLiteDatabase mDatabase;

    protected TestSqlite(Context context) {
        TestSqlite.mInstance = this;
        mDatabase = context.openOrCreateDatabase("select.db", Context.MODE_PRIVATE, null);
        migrate();
    }

    private void migrate() {
        final int version = mDatabase.getVersion();
        final int currentVersion = 1;
        if (version >= currentVersion) {
            return;
        }

        mDatabase.beginTransaction();

        switch (version) {
            case 0:
                createTables();
            break;
        }
        mDatabase.setTransactionSuccessful();
        mDatabase.setVersion(currentVersion);
        mDatabase.endTransaction();

        // 整理数据库
        mDatabase.execSQL("VACUUM");
    }

    private void createTables() {
        mDatabase.execSQL("create table if not exists Students(id integer primary key, name text not null)");
        mDatabase.execSQL("create table if not exists Subjects(id integer primary key, name text not null)");
        mDatabase.execSQL("create table if not exists Subject_Select(id integer primary key, "
                + "student_id integer references Students(id), " + "subject_id integer references Subjects(id),"
                + "unique_check text unique not null)");
    }
}

由于使用的单例,要重写application:

public class TestApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        new TestSqlite(getApplicationContext());
    }

}

在AndroidManifest.xml中添加application

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.testsqlite"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="4"
        android:targetSdkVersion="8"
        tools:ignore="OldTargetApi" />

    <application
        android:name="com.example.database.TestApplication"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.testsqlite.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

代码结构为:

运行程序,会在私有目录创建数据库

在TestSqlite加入插入student和subject的代码

    private SQLiteStatement mInsertStudentInfoStatement;

    public long insertStudentInfo(long id, String name) {
        if (name == null) {
            return -1;
        }

        if (mInsertStudentInfoStatement == null) {
            mInsertStudentInfoStatement = mDatabase.compileStatement("insert or ignore into Students values (?,?)");
        }
        mInsertStudentInfoStatement.bindLong(1, id);
        mInsertStudentInfoStatement.bindString(2, name);
        return mInsertStudentInfoStatement.executeInsert();
    }

    private SQLiteStatement mInsertSubjectInfoStatement;

    public long insertSubjectInfo(long id, String name) {
        if (name == null) {
            return -1;
        }
        if (mInsertSubjectInfoStatement == null) {
            mInsertSubjectInfoStatement = mDatabase.compileStatement("insert or ignore into Subjects values (?,?)");
        }
        mInsertSubjectInfoStatement.bindLong(1, id);
        mInsertSubjectInfoStatement.bindString(2, name);
        return mInsertSubjectInfoStatement.executeInsert();
    }

这两个操作没有使用execSQL而是使用的SQLiteStatement,这样可以提高效率。

插入选课代码为:

    private SQLiteStatement mInsertSubjectSelectStatement;

    public long insertSubjectSelectInfo(long student_id, long subject_id) {

        if (mInsertSubjectSelectStatement == null) {
            mInsertSubjectSelectStatement = mDatabase
                    .compileStatement("insert or ignore into Subject_Select(student_id, subject_id, unique_check) values (?,?,?)");
        }
        String uniqueCheck = student_id + "_" + subject_id;
        mInsertSubjectSelectStatement.bindLong(1, student_id);
        mInsertSubjectSelectStatement.bindLong(2, subject_id);
        mInsertSubjectSelectStatement.bindString(3, uniqueCheck);
        return mInsertSubjectSelectStatement.executeInsert();
    }

Subject_Select表的主键id自动生成,student_id和subject_id添加了references进行约束,必须是Students和Subjects表中的数据。unique_check添加了unique约束,内容为使用student_id和subject_id拼成的一个字符串,防止插入重复的数据

在MainActiviy中进行测试

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TestSqlite.Instance().insertStudentInfo(1, "小明");
        TestSqlite.Instance().insertStudentInfo(2, "小白");
        TestSqlite.Instance().insertSubjectInfo(1, "数学");
        TestSqlite.Instance().insertSubjectInfo(2, "语文");
        TestSqlite.Instance().insertSubjectInfo(3, "英语");
        TestSqlite.Instance().insertSubjectInfo(4, "物理");
        TestSqlite.Instance().insertSubjectInfo(5, "化学");
        TestSqlite.Instance().insertSubjectSelectInfo(1, 1);
        TestSqlite.Instance().insertSubjectSelectInfo(1, 3);
        TestSqlite.Instance().insertSubjectSelectInfo(1, 4);
        TestSqlite.Instance().insertSubjectSelectInfo(2, 2);
        TestSqlite.Instance().insertSubjectSelectInfo(2, 4);
        TestSqlite.Instance().insertSubjectSelectInfo(2, 5);
    }
}

通过学生的id查询所选的课程名称:

    public List<String> getSelectSubjectNameByStudentId(long id) {
        List<String> list = new ArrayList<String>();

        String[] args = new String[] { id + "" };
        Cursor cursor = mDatabase.rawQuery("select subjects.name from subjects,subject_select " +
                "where subject_select.student_id = ? " +
                "and subject_select.subject_id = subjects.id", args);
        while (cursor.moveToNext()) {
            list.add(cursor.getString(0));
        }

        return list;
    }

使用的cursor中有一点要注意,在拼接SQL语句的时候,可以直接将参数拼到字符串里,例如:

Cursor cursor2 = mDatabase.rawQuery("select name from Students where id = " + id, null);

也可以

Cursor cursor2 = mDatabase.rawQuery("select name from Students where id = ?", new String[] { id + "" });

一般情况下,这两种写法效果是一样的,但是第二种方法的优点是不用考虑转义字符,像 \%$&/" 这样的字符串直接就可以使用,而第一种方法要考虑进行转义,否则不能正常进行识别。

测试查询的代码:

        List<String> list = TestSqlite.Instance().getSelectSubjectNameByStudentId(1);
        for (String item : list) {
            Log.i(getClass().getName(), item);
        }

至此,一个简单的数据库就设计完成了,经过进一步的完善,软件上线了,在开发2.0的时候,又有了一新的需求,要有课程的分数,这就需要在Subject_Select表添加一个新的字段score。又要保留之前的数据,在1.0的基础上进行升级,又要添加新的功能,这就需要对数据库进行重构。

我们要做的就是

1)将Subject_Select重命名为Subject_Select_Obsolete

2)按新的需求新建一个Subject_Select

3)将Subject_Select_Obsolete的数据复制到Subject_Select

4)删除Subject_Select_Obsolete

SQL语句为

alter table Subject_Select rename to Subject_Select_Obsolete
create table Subject_Select(id integer primary key, student_id integer references Students(id), subject_id integer references Subjects(id),unique_check text unique not null, score real)
insert into Subject_Select (id,student_id,subject_id,unique_check) select id,student_id,subject_id,unique_check from Subject_Select_Obsolete
drop table Subject_Select_Obsolete

首先要在代码中进行判断:

    private void migrate() {
        final int version = mDatabase.getVersion();
        final int currentVersion = 2;
        if (version >= currentVersion) {
            return;
        }

        mDatabase.beginTransaction();

        switch (version) {
            case 0: {
                createTables();
                break;
            }
            case 1: {
                updateTaples1();
                break;
            }
            default:
            break;
        }
        mDatabase.setTransactionSuccessful();
        mDatabase.setVersion(currentVersion);
        mDatabase.endTransaction();

        // 整理数据库
        mDatabase.execSQL("VACUUM");
    }

在上面的代码中,如果数据库版本为0,说明不存在就的数据库,直接创建表,如果数据库版本为1,说明有老版本的数据库,要对数据库进行升级。不管是升级还是全新的创建,数据库的版本都设置为2。

数据库升级的代码为:

    private void updateTaples1() {
        mDatabase.execSQL("alter table Subject_Select rename to Subject_Select_Obsolete");
        mDatabase.execSQL("create table Subject_Select(id integer primary key, student_id integer references Students(id), subject_id integer references Subjects(id),unique_check text unique not null, score real)");
        mDatabase.execSQL("insert into Subject_Select (id,student_id,subject_id,unique_check) select id,student_id,subject_id,unique_check from Subject_Select_Obsolete");
        mDatabase.execSQL("drop table Subject_Select_Obsolete");
    }

Android Sqlite 实例入门的更多相关文章

  1. Android——SQLite/数据库 相关知识总结贴

    android SQLite简介 http://www.apkbus.com/android-1780-1-1.html Android SQLite基础 http://www.apkbus.com/ ...

  2. android 开发从入门到精通

    Android-Tips This is an awesome list of tips for android. If you are a beginner, this list will be t ...

  3. 使用 Eclipse PhoneGap 构建 Android 应用程序入门

    Eclipse 是一种支持多种技术的开源集成开发环境 (IDE),但本文重点介绍 Java 支持,这也是 Android 应用程序的“母语”.Android 是 Google 发布的开源移动操作系统. ...

  4. Android SQLite总结(一) (转)

    Android SQLite总结(一)  郑海波 2012-08-21 转载请声明:http://blog.csdn.net/nuptboyzhb/article/details/7891887 前言 ...

  5. 一看就懂的Android APP开发入门教程

    一看就懂的Android APP开发入门教程 作者: 字体:[增加 减小] 类型:转载   这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤 ...

  6. Android SQLite 数据库详细介绍

    Android SQLite 数据库详细介绍 我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用 ...

  7. 一个简单的Android小实例

    原文:一个简单的Android小实例 一.配置环境 1.下载intellij idea15 2.安装Android SDK,通过Android SDK管理器安装或卸载Android平台   3.安装J ...

  8. Android SQLite 数据库 增删改查操作

    Android SQLite 数据库 增删改查操作 转载▼ 一.使用嵌入式关系型SQLite数据库存储数据 在Android平台上,集成了一个嵌入式关系型数据库--SQLite,SQLite3支持NU ...

  9. Android SQLite 简易指北

    Android SQLite SQLite一款开源的, 轻量级的数据库. 以文本文件的形式存储数据. SQLite支持所有标准的关系型数据库特性. SQLite运行时占用内存非常少(约250 KByt ...

随机推荐

  1. MFC设置静态文本框,编辑框等控件背景和字体颜色

    在MFC类库提供了CWnd::OnCtlColor函数,在工作框架的子窗口被重画时将调用该成员函数.因此可以重载WM_CTLCOLOR消息的响应函数.此函数的原型:afx_msg HBRUSH OnC ...

  2. oracle监听程序无法启动(TNS-12560: TNS: 协议适配器错误,TNS-00530: 协议适配器错误)

    问题描述1:   C:\Users\Administrator>lsnrctl start LSNRCTL for 64-bit Windows: Version 11.2.0.1.0 - Pr ...

  3. MFC ADO连接Oracle12c数据库 服务端配置

    要想客户端访问服务器端的oracle数据库的话,还需要服务端设置下监听程序及本地网络服务名配置. 发现百度文库上面有这方面的文档,我就不重复写了.请参照一下网址: http://wenku.baidu ...

  4. webpack+vue-loader 在单独.vue组件中使用sass-loader编译sass报错问题not a valid Win32 applictation

        如果webpack配置没有问题,在vue文件中编译sass/scss报上面的错误,大概是由于node-sass安装失败,重新卸载安装,   在国内安装node-sass失败的话,可以使用淘宝镜 ...

  5. 伸展树(三)之 Java的实现

    概要 前面分别通过C和C++实现了伸展树,本章给出伸展树的Java版本.基本算法和原理都与前两章一样.1. 伸展树的介绍2. 伸展树的Java实现(完整源码)3. 伸展树的Java测试程序 转载请注明 ...

  6. GOCR.js – 使用 JS 识别出图片中的文本

    GOCR.js 是 GOCR(开源的 OCR 光学识别程序)项目的纯 JavaScript 版本,使用 Emscripten 进行自动转换.这是一个简单的 OCR (光学字符识别)程序,可以扫描图像中 ...

  7. 关于开发Windows服务程序容易搞混的地方!

    在开发Windows服务程序时,我们一般需要添加安装程序,即:serviceInstaller,里面有几个关于名称属性,你都搞明白了吗? 1.Description:表示服务说明(描述服务是干什么的) ...

  8. SQL Server技术问题之自定义函数优缺点

    优点: 可以在SQL语句中调用,直接使用返回值,从而可以形成复杂的SQL应用. 缺点: 能在函数中使用的语句有严格限制: 不支持create.ALTER.drop等DDL(Data Definitio ...

  9. “康园圈--互联网+校园平台“项目之sprint2

    一.sprint2任务列表 1.部署框架,并上传代码到github. 2.原型设计 * 设计首页界面原型(包括功能公告.快速通道等展示栏) * 设计店铺浏览页面原型 * 设计店内浏览页面原型 * 设计 ...

  10. 区间合并 --- Codeforces 558D : Gess Your Way Out ! II

    D. Guess Your Way Out! II Problem's Link: http://codeforces.com/problemset/problem/558/D Mean: 一棵满二叉 ...