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语句例如以下图所看到的
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1eHU4NDE5MTE1NDg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="创建表" title="">
(3)插入数据
SQL语句插入数据的关键字为insert。完整的格式例如以下图所看到的
比如在classes表中插入一条数据,这里我仅仅插入了一条数据中的2个字段,写法例如以下图
注意:插入的这些数据在表中一定要有相应的字段。不然就会报错!
insert语句支持批量插入数据,比方我要把students表中的数据都导入表stu中。SQL语句为
insert into stu select * from students;
(4)查询语句
Select语句的通用格式例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGl1eHU4NDE5MTE1NDg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="查询语句标准格式" title="">
这段语句简单解释一下,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;
}
}
这些知识都是数据库的基础知识。当然复杂的知识也是在基础知识的基础上拼接起来的,先学好了基础才干谈复杂项目中多个表多个字段数据库的运用!
我非常喜欢的一句话,不积跬步无以至千里,一直陪伴着我的学习和工作!
不足之处请指正。谢谢!
10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)的更多相关文章
- PHPCMS中GET标签概述、 get 标签语法、get 标签创建工具、get 调用本系统演示样例、get 调用其它系统演示样例
一.get 标签概述 通俗来讲,get 标签是Phpcms定义的能直接调用数据库里面内容的简单化.友好化代码,她可调用本系统和外部数据,仅仅有你对SQL有一定的了解,她就是你的绝世好剑!也就是适合熟悉 ...
- Android线程池(二)——ThreadPoolExecutor及其拒绝策略RejectedExecutionHandler使用演示样例
MainActivity例如以下: package cc.vv; import java.util.concurrent.LinkedBlockingQueue; import java.util.c ...
- JDBC连接MySQL数据库及演示样例
JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术. 一.JDBC基础知识 JDBC(Java Data Base Connectivity,java数据库连接)是一种用 ...
- [转帖]SQL Server 10分钟理解游标
SQL Server 10分钟理解游标 https://www.cnblogs.com/VicLiu/p/11671776.html 概述 游标是邪恶的! 在关系数据库中,我们对于查询的思考是面向集合 ...
- 10分钟理解BFC原理
10 分钟理解 BFC 原理 一.常见定位方案 在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案: 普通流 (normal flow) 在普通流中,元素按照 ...
- android listview综合使用演示样例_结合数据库操作和listitem单击长按等事件处理
本演示样例说明: 1.自己定义listview条目样式,自己定义listview显示列数的多少,灵活与数据库中字段绑定. 2.实现对DB的增删改查,而且操作后listview自己主动刷新. 3.响应用 ...
- Android之——流量管理程序演示样例
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47680811 眼下.市面上有非常多管理手机流量的软件,能够让用户实时获取到自己手机 ...
- [Android]RecyclerView的简单演示样例
去年google的IO上就展示了一个新的ListView.它就是RecyclerView. 下面是官方的说明,我英语能力有限,只是我大概这么理解:RecyclerView会比ListView更具有拓展 ...
- Android通过startService播放背景音乐简单演示样例
关于startService的基本使用概述及其生命周期可參见博客<Android中startService的使用及Service生命周期>. 本文通过播放背景音乐的简单演示样例,演示sta ...
随机推荐
- MySQL查询语句执行过程及性能优化-基本概念和EXPLAIN语句简介
网站或服务的性能关键点很大程度在于数据库的设计(假设你选择了合适的语言开发框架)以及如何查询数据上. 我们知道MySQL的性能优化方法,一般有建立索引.规避复杂联合查询.设置冗余字段.建立中间表.查询 ...
- P3512 [POI2010]PIL-Pilots
P3512 [POI2010]PIL-Pilots我一开始打的O(n^2)(最坏情况)的算法.枚举区间长度.60分 #include<iostream> #include<cstdi ...
- InnoDB的锁机制浅析(五)—死锁场景(Insert死锁)
可能的死锁场景 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意 ...
- html (第四本书第1~3章参考)
前三章都不会的话 呵呵……
- 使用Synchronized块同步变量
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特定的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- 【转载】C语言 构建参数个数不固定函数
深入浅出可变参数函数的使用技巧本文主要介绍可变参数的函数使用,然后分析它的原理,程序员自己如何对它们实现和封装,最后是可能会出现的问题和避免措施. VA函数(variable argument fun ...
- Slickflow.NET 开源工作流引擎高级开发(一) -- 流程外部事件的调用和变量存储实现
前言:流程实现基本流转功能外,通常也需要调用外部事件,用于和业务系统的交互,同时存储一些流程变量,用于追踪和记录业务数据变化对流程流转的影响. 1. 流程事件 流程执行过程中,伴随各种事件的发生,而且 ...
- 通过本地Git部署网站到WebSite
玩过Azure WebSite(WebApp)的同学应该知道部署网站的方式非常多,今天我要讲的是如果通过本地Git部署网站到WebSite. 1.新建WebSite 创建WebSite非常简单,我这里 ...
- gdb调试报错:Missing separate debuginfos, use: debuginfo-install glibc-XXX
解决方案: 1.先修改“/etc/yum.repos.d/CentOS-Debuginfo.repo”文件的 enable=1: 2.使用 sudo yum install glibc 安装: 3.使 ...
- 在ASP.NET Web API中使用OData的单例模式
从OData v4开始增加了对单例模式的支持,我们不用每次根据主键等来获取某个EDM,就像在C#中使用单例模式一样.实现方式大致需要两步: 1.在需要实现单例模式的导航属性上加上[Singleton] ...