• 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)


    1.Android数据库简单介绍.
    Android系统的framework层集成了Sqlite3数据库。我们知道Sqlite3是一种轻量级的高效存储的数据库。
    Sqlite数据库具有以下长处:
    (1)零配置,无需安装和配置;
    (2)储存在单一磁盘文件里的一个完整的数据库。
    (3)数据库文件能够在不同字节顺序的机器间自由共享;
    (4)支持数据大小至2TB;
    (5)足够小。全部源码大致3万行C代码。250KB;
    (6)比眼下流行的大多数数据库的操作要快。
    (7)开源。

    2.Sqlite 基本操作语句和重要概念

    (1)创建数据库

    创建数据库实际上并不是通过SQL语句来创建。创建数据库能够通过sqlite3 新数据库名 来创建,比方创建一个名为school.db的数据库,在命令行下输入“sqlite3 school.db;”就可以。

    (2)创建表

    创建表的SQL语法为:
    create table 表名(字段1 数据约束类型,…,字段n 数据约束类型)。
    注意:每一条SQL语句都以分号结尾
    Sqlite数据库支持的数据库类型大致分为5种。各自是:

    NUll 数据值为空
    INTEGER 整型
    REAL 浮点型数据
    TEXT 字符类型,使用数据库编码(UTF-8等)存放
    BLOB 仅仅是一个数据块,全然依照输入存放

    注意:SQLite3数据库中不论什么列,除了整形主键列,能够用于存储不论什么一个存储列的值,SQLite没有单独的布尔存储类型,你能够使用INTEGER的0和1表示true和false,另外。SQLite也没有代表时间和日期的数据类型。能够转化为TEXT或者INTEGER来存储
    经常使用的数据库约束包括以下几种:

    PRIMARY KEY 主键 它是非空且唯一的
    NOT NULL 非空
    UNIQUE 唯一
    FOREIGN KEY 外键
    CHECK 条件检查
    DEFAULT 字段的默认值

    以下举例说明创建一个班级表,表中有3个字段,各自是自增的主键id、专业、年份。

    创建表的SQL语句例如以下图所看到的

    创建表

    (3)插入数据

    SQL语句插入数据的关键字为insert。完整的格式例如以下图所看到的

    插入数据

    比如在classes表中插入一条数据,这里我仅仅插入了一条数据中的2个字段,写法例如以下图

    classes表中插入数据
    注意:插入的这些数据在表中一定要有相应的字段。不然就会报错!

    insert语句支持批量插入数据,比方我要把students表中的数据都导入表stu中。SQL语句为

    insert into stu select * from students;

    (4)查询语句
    Select语句的通用格式例如以下:

    查询语句标准格式

    这段语句简单解释一下,columns是要查询的字段,tables表示从哪张表里面查询,where是查询过滤的条件,group by是指依照某个字段分组查询。order by是排序,limit是限制数量语句,以下我会一一解释每一个语句须要注意的地方。

    1.字段与表的别名
    多表查询时查询条件相对复杂,表之间可能会产生同样的字段,这个时候字段前面能够加上表名以区分。别名就是我们能够将classes的表名设置为cls。将classes表中的major字段显示为cmj字段以简化SQL语句。

    2.where条件过滤

    where语句中经常使用的逻辑操作符有and、or、not,分别代表与、或、非。

    注意where中有一个较为重要的关系操作符叫做like。它是模糊匹配。比如要找到students表中以t开头的全部学生,那么相应的SQL为:

    select * from students where name like “t%”;

    3.Group by 分组

        聚合中有一个重要的功能就是分组。分组就是将得到的结果集依照一定的规则划分为多个组。
    

    因为该功能不常使用,想要了解的朋友自行查阅资料。

    4.排序
    select结果集的排序使用的是order by字句。排序有升序和降序两种。分别相应asc和desc,order by后面紧跟一个或者多个字段。多个字段间用逗号隔开。

    5.数量限定
    数量限定须要使用limit语句。数量限定的标准格式例如以下:

        limit 返回的数量 offset 偏移量
    

    比如我们希望从students中索引为3的记录開始索引而且仅仅返回一条语句,SQL例如以下:

    select * from students limit 1 offset 2;

    6.distinct去重

        distinct用于去除select语句中反复的行。它紧跟在select之后。
    

    (5)update 语句

    update 语句用于更新表中的数据,它的格式为:

    update table set update_list where predicate;
        update_list是要改动的字段以及值。事实上就是一个字段赋值语句,形式为:字段名 = 字段值,每一个字段赋值语句通过逗号分隔开。兴许我会在具体的演示样例代码中举例,在这就只是多阐述。
    

    (6)delete语句
    delete语句的格式例如以下:

    //当满足where的条件时。删除表table中的数据。table是表名
    delete from table where predicate;

    (7)改动表

        我们知道。随着项目的演化,最初建立的表可能会面临改动的情况。

    改动表的SQL语句命令为alter。SQLite中的alter命令并没有实现标准SQL中的全部功能,**它仅仅有改动表名和加入字段两个功能**,**删除字段等功能仅仅能通过又一次创建表来实现**。

    alter的语法格式为:

    alter table tableName {rename to newName | add column 新的字段};
        上述的语法表示alter table之后要操作先跟表名,然后rename to newName 和add column 新的字段两者2选1。rename to 是重命名。add column是加入新的字段。
    

    (8)drop 命令

        drop命令用于删除物理存储介质。

    比如删除表、视图、索引、触发器等。

    drop的语法格式为:

    drop {table | view |index |trigger} name;

    (9)数据库事务的介绍

        事务是一个数据库操作的运行单元。它定义了一条或多条SQL语句,这些语句要么被全部运行。要么全部不运行。它保证了SQL语句的原子性。

    事务有begin、commit、rollback3个命令。begin表示開始一个事务,commit表示整个事务操作成功,rollback表示回滚到begin之前。

    格式为:

    begin。
    //SQL语句
    [commit | rollback];

    注意:事务提供了一种保证多条SQL语句能够被运行或者不运行。非常大程度上保证了数据库操作的安全性。而在Android中使用事务。也会提升SQL的运行效率。

        事务的运用简单举个样例,张三给李四转账400元。银行的数据库中张三的存款金额要减400,李四的存款金额要加400,我们要保证张三扣钱的通过李四收到钱。这个时候就须要用到数据库事务,要么两条SQL语句同一时候成功,要么同一时候失败。
    

    (10)Android中封装的数据库帮助接口

        我们知道Android的SQLite数据库是由C和C++实现,因此Android在FrameWork层封装了一层Java接口,使得开发者能够更方便的操作数据库。

    基本的类型为SQLiteOpenHelper、SQLiteDatabase以及Cusor。无论怎样封装。本质上都是通过构建SQL语句而且提交到SQLite中运行。以下具体介绍。Android中创建数据库创建表的全部方法。

    3.使用Android的接口创建和操作数据库

    一般来说,在Android中创建数据库仅仅须要以下几步:

    (1)创建一个Java类继承SQLiteOpenHelper
    (2)实现SQLiteOpenHelper的onCreate和onUpdate方法以及构造方法。


    (3)通过构造方法创建数据库,须要传入数据库的名称。Context和数据库的版本。
    (4)在onCreate中完毕创建表和字段的操作,onUpdate中完毕升级操作
    (5)通过帮助类的openOrCreateDatabase()方法或者getReadableDatabase()或者getWriteableDatabase()获取到数据库完毕数据的操作。

    以下附上我的写的一个演示样例代码,当中封装了推断数据库是否存在某个表,是否存在某个字段的方法

    数据库的帮助类,完毕了创建数据库,创建表

    package com.geocompass.gisdatacollection.database;
    
    import android.content.Context;
    import android.database.Cursor;
    import android.database.DatabaseErrorHandler;
    import android.database.sqlite.SQLiteDatabase;
    import android.database.sqlite.SQLiteOpenHelper;
    import android.os.Environment;
    
    import com.geocompass.gisdatacollection.CollectionApplication;
    
    import java.io.File;
    
    /**
     * Created by liuxu on 2017/4/7.
     * 数据库的操作的帮助类
     */
    
    public class ComplexDatabaseSqlHelper extends SQLiteOpenHelper {
        private static final String TAG = "ComplexDatabaseSqlHelper";
        //数据库的版本
        private static final int DB_VERSION = 1;
    
        public SQLiteDatabase getDb() {
            return db;
        }
    
        private SQLiteDatabase db;
        //数据库db文件的路径,由调用者传入
        private static String mDBPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "giscoll.db";
    
        private static ComplexDatabaseSqlHelper mDBSqlHelper;
    
        public ComplexDatabaseSqlHelper(Context context, String DBpath) {
            super(context, DBpath, null, DB_VERSION);
            mDBPath = DBpath;
            if (db == null) {
                db = SQLiteDatabase.openOrCreateDatabase(DBpath, null);
            }
            onCreate(db);
        }
    
        public ComplexDatabaseSqlHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }
    
        public ComplexDatabaseSqlHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
            super(context, name, factory, version, errorHandler);
        }
    
        @Override
        public void onCreate(SQLiteDatabase db) {
            String CREATE_POINT = "create table tab_point ("
                    + "id integer primary key autoincrement,"
                    + "lon double, "
                    + "lat double, "
                    + "type integer) ";
            String CREATE_INTERSECTION = "create table tab_intersection ("
                    + "inter_id integer primary key autoincrement,"
                    + "interLon double, "
                    + "interLat double, "
                    + "interRouteID text) ";
            String CREATE_ROUTE = "create table tab_route ("
                    + "route_name text,"
                    + "startPointID integer, "
                    + "endPointID integer, "
                    + "geometryID text, "
                    + "Geometry text) ";
            ;
            //假设不存在该表。则创建该表
            if (!tableIsExist("tab_point")) {
                db.execSQL(CREATE_POINT);
            }
            if (!tableIsExist("tab_intersection")) {
                db.execSQL(CREATE_INTERSECTION);
            }
            if (!tableIsExist("tab_route")) {
                db.execSQL(CREATE_ROUTE);
            }
    
        }
    
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    
        }
    
        /**
         * 获取数据库的帮助类
         *
         * @return
         */
        public static ComplexDatabaseSqlHelper getDBSqlHelper() {
            if (mDBSqlHelper == null) {
                synchronized (ComplexDatabaseSqlHelper.class) {
                    if (mDBSqlHelper == null) {
                        mDBSqlHelper = new ComplexDatabaseSqlHelper(CollectionApplication.getmContext(), mDBPath);
                    }
                }
            }
            return mDBSqlHelper;
        }
    
        /**
         * 依据sql查询数据库的方法
         *
         * @param sql
         * @return
         */
        public Cursor query(String sql) {
            return db.rawQuery(sql, null);
        }
    
        /**
         * 运行Sql语句
         *
         * @param sql
         */
        public void execSQL(String sql) {
            db.execSQL(sql);
        }
    
        /**
         * 推断表格是否存在
         *
         * @param tableName
         * @return
         */
        public boolean tableIsExist(String tableName) {
            boolean result = false;
            if (tableName == null) {
                return false;
            }
            Cursor cursor = null;
            try {
                //db = SQLiteDatabase.openDatabase(this.mDBPath,null,SQLiteDatabase.OPEN_READONLY);
                String sql = "select count(*) as c from Sqlite_master where type ='table' and name ='" + tableName.trim() + "' ";
                cursor = db.rawQuery(sql, null);
                if (cursor.moveToNext()) {
                    int count = cursor.getInt(0);
                    if (count > 0) {
                        result = true;
                    }
                }
                cursor.close();
            } catch (Exception e) {
                // TODO: handle exception
                result = false;
            }
            return result;
        }
    
        /**
         * 推断表中是否包括某个字段
         *
         * @param tableName
         * @param columnName
         * @return
         */
        public boolean columnIsExistsInTable(String tableName, String columnName) {
            boolean result = false;
            Cursor cursor = null;
            try {
                //  db = SQLiteDatabase.openDatabase(this.mDBPath, null, SQLiteDatabase.OPEN_READONLY);
                cursor = db.rawQuery("select * from sqlite_master where name = ? and sql like ?

    " , new String[]{tableName, "%" + columnName + "%"}); result = null != cursor && cursor.moveToFirst(); } catch (Exception ignored) { } finally { if (null != cursor && !cursor.isClosed()) { cursor.close(); } } return result; } private void open() { if (db != null && !db.isOpen()) db = SQLiteDatabase.openOrCreateDatabase(mDBPath, null); } }

    数据库的操作类,完毕了对数据库表中数据的插入和查询

    package com.geocompass.gisdatacollection.database.manage;
    
    import android.database.Cursor;
    import android.database.SQLException;
    import android.database.sqlite.SQLiteDatabase;
    
    import com.geocompass.gisdatacollection.model.Intersection;
    import com.geocompass.gisdatacollection.model.Point;
    import com.geocompass.gisdatacollection.model.Route;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by liuxu on 2017/4/10.
     * 封装了对数据库表的增删改查方法
     */
    
    public class ComplexDBDao {
        private SQLiteDatabase db;
        public ComplexDBDao(SQLiteDatabase db) {
            this.db = db;
        }
    
        /**
         * 插入一个点到tab_point表
         * @param point
         * @return
         */
        public boolean insert(Point point){
            String INSERT_POINT = "INSERT INTO tab_point(lon,lat,type) VALUES (" + point.lon + "," + point.lat + "," + point.point_type + ")";
            try{
                db.execSQL(INSERT_POINT);
            }catch(SQLException e){
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        /**
         * 插入一个节点到tab_intersection表中
         * @param intersection
         * @return
         */
        public boolean insert(Intersection intersection){
            String INSERT_INTERSECTION = "insert into tab_intersection(interLon,interLat,interRouteID) values ("+intersection.interLon+","+intersection.interLat+",'"+
                    intersection.inter_route_id+"')";
            try{
                db.execSQL(INSERT_INTERSECTION);
            }catch(SQLException e){
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        /**
         * 插入一条Route到tab_route表中
         * @param route
         * @return
         */
        public boolean insert(Route route){
            String  INSERT_ROUTE = "insert into tab_route (route_name,startPointID,endPointID,geometryID,Geometry) values('"+route.route_name+
                    "',"+route.startPointID+","+route.endPointID+",'"+route.geometryID+"','"+route.Geometry+"')";
            try{
                db.execSQL(INSERT_ROUTE);
            }catch(SQLException e){
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        /**
         * 查询出数据库中全部的Points
         * @return
         */
        public List<Point> findAllTabPoint(){
            String sql_select = "select * from tab_point order by id";
            //请补充sql运行语句
            Cursor cursor = db.rawQuery(sql_select,null);
            int IDIndex = cursor.getColumnIndex("id");
            int lonIndex = cursor.getColumnIndex("lon");
            int latIndex = cursor.getColumnIndex("lat");
            int typeIndex = cursor.getColumnIndex("type");
            List<Point> list = new ArrayList<>();
            while (cursor.moveToNext()) {
                Point point = new Point();
                point.id = cursor.getInt(IDIndex);
                point.lon = cursor.getDouble(lonIndex);
                point.lat = cursor.getDouble(latIndex);
                point.point_type = cursor.getInt(typeIndex);
                list.add(point);
            }
            return list;
        }
    
        /**
         * 查询出数据库中全部的Intersection
         * @return
         */
        public List<Intersection> findAllTabIntersection(){
            String sql_select = "select * from tab_intersection order by inter_id";
            //请补充sql运行语句
            Cursor cursor = db.rawQuery(sql_select,null);
            int interIdIndex = cursor.getColumnIndex("inter_id");
            int interLonIndex = cursor.getColumnIndex("interLon");
            int interLatIndex = cursor.getColumnIndex("interLat");
            int interRouteIDIndex = cursor.getColumnIndex("interRouteID");
            List<Intersection> list = new ArrayList<>();
            while (cursor.moveToNext()) {
                Intersection intersection = new Intersection();
                intersection.inter_id = cursor.getInt(interIdIndex);
                intersection.interLon = cursor.getDouble(interLonIndex);
                intersection.interLat = cursor.getDouble(interLatIndex);
                intersection.inter_route_id = cursor.getString(interRouteIDIndex);
                list.add(intersection);
            }
            return list;
        }
    
        /**
         * 查询出数据库中全部的Route
         * @return
         */
        public List<Route> findAllTabRoute(){
            String sql_select = "select * from tab_route ";
            //请补充sql运行语句
            Cursor cursor = db.rawQuery(sql_select,null);
            int routeNameIndex = cursor.getColumnIndex("route_name");
            int startPointIDIndex = cursor.getColumnIndex("startPointID");
            int endPointIDIndex = cursor.getColumnIndex("endPointID");
            int geometryIDIndex = cursor.getColumnIndex("geometryID");
            int geometryIndex = cursor.getColumnIndex("Geometry");
            List<Route> list = new ArrayList<>();
            while (cursor.moveToNext()) {
                Route route = new Route();
                route.route_name = cursor.getString(routeNameIndex);
                route.startPointID = cursor.getInt(startPointIDIndex);
                route.endPointID = cursor.getInt(endPointIDIndex);
                route.geometryID = cursor.getString(geometryIDIndex);
                route.Geometry = cursor.getString(geometryIndex);
                list.add(route);
            }
            return list;
        }
    }
    

    这些知识都是数据库的基础知识。当然复杂的知识也是在基础知识的基础上拼接起来的,先学好了基础才干谈复杂项目中多个表多个字段数据库的运用!

    我非常喜欢的一句话,不积跬步无以至千里,一直陪伴着我的学习和工作!


    不足之处请指正。谢谢!

  • 相关阅读:
    洛谷P3811题解
    洛谷P3353在你窗外闪耀的星星-题解
    Map根据value来排序
    java8 groupby count
    Java反射
    maven profile环境切换
    获取nginx代理情况下的真实ip
    获取request里header的name和value
    git 删除iml文件
    java list 排序
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7389083.html
Copyright © 2020-2023  润新知