一、前言:
SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就够了,SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID事务。
1. 什么是 SQLite?
SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库一样,您不需要在系统中配置。
就像其他数据库,SQLite 引擎不是一个独立的进程,可以按应用程序需求进行静态或动态连接。SQLite 直接访问其存储文件。
一个事务本质上有四个特点ACID:
- Atomicity原子性
- Consistency一致性
- Isolation隔离性
- Durability耐久性
2. 为什么要用 SQLite?
- 不需要一个单独的服务器进程或操作的系统(无服务器的)。
- SQLite 不需要配置,这意味着不需要安装或管理。
- 一个完整的 SQLite 数据库是存储在一个单一的跨平台的磁盘文件。
- SQLite 是非常小的,是轻量级的,完全配置时小于 400KiB,省略可选功能配置时小于250KiB。
- SQLite 是自给自足的,这意味着不需要任何外部的依赖。
- SQLite 事务是完全兼容 ACID 的,允许从多个进程或线程安全访问。
- SQLite 支持 SQL92(SQL2)标准的大多数查询语言的功能。
- SQLite 使用 ANSI-C 编写的,并提供了简单和易于使用的 API。
- SQLite 可在 UNIX(Linux, Mac OS-X, Android, iOS)和 Windows(Win32, WinCE, WinRT)中运行。
二、基本语法:
1. SQLite 命令
与关系数据库进行交互的标准 SQLite 命令类似于 SQL。命令包括 CREATE、SELECT、INSERT、UPDATE、DELETE 和 DROP。这些命令基于它们的操作性质可分为以下几种:
DDL - 数据定义语言
命令 | 描述 |
---|---|
CREATE | 创建一个新的表,一个表的视图,或者数据库中的其他对象。 |
ALTER | 修改数据库中的某个已有的数据库对象,比如一个表。 |
DROP | 删除整个表,或者表的视图,或者数据库中的其他对象。 |
DML - 数据操作语言
命令 | 描述 |
---|---|
INSERT | 创建一条记录。 |
UPDATE | 修改记录。 |
DELETE | 删除记录。 |
DQL - 数据查询语言
命令 | 描述 |
---|---|
SELECT | 从一个或多个表中检索某些记录。 |
2. SQLite 语法
- SQLite 是不区分大小写的,但也有一些命令是大小写敏感的,比如 GLOB 和 glob 在 SQLite 的语句中有不同的含义。
- 所有的 SQLite 语句可以以任何关键字开始,如 SELECT、INSERT、UPDATE、DELETE、ALTER、DROP 等,所有的语句以分号(;)结束。
3. SQLite 数据类型
SQLite 数据类型是一个用来指定任何对象的数据类型的属性。SQLite 中的每一列,每个变量和表达式都有相关的数据类型。
您可以在创建表的同时使用这些数据类型。SQLite 使用一个更普遍的动态类型系统。在 SQLite 中,值的数据类型与值本身是相关的,而不是与它的容器相关。
SQLite 存储类
每个存储在 SQLite 数据库中的值都具有以下存储类之一:
存储类 | 描述 |
---|---|
NULL | 值是一个 NULL 值。 |
INTEGER | 值是一个带符号的整数,根据值的大小存储在 1、2、3、4、6 或 8 字节中。 |
REAL | 值是一个浮点值,存储为 8 字节的 IEEE 浮点数字。 |
TEXT | 值是一个文本字符串,使用数据库编码(UTF-8、UTF-16BE 或 UTF-16LE)存储。 |
BLOB | 值是一个 blob 数据,完全根据它的输入存储。 |
注意:
- SQLite 没有单独的 Boolean 存储类。相反,布尔值被存储为整数 0(false)和 1(true)。
- SQLite 没有一个单独的用于存储日期和/或时间的存储类,但 SQLite 能够把日期和时间存储为 TEXT、REAL 或 INTEGER 值。
三、基本用法:
1. MyDatabaseHelper类
Android 提供的 SQLiteOpenHelper.java 是一个抽象类。那么我们要使用它,必须自己写一个类来继承它,实现它的抽象方法。
public class MyDatabaseHelper extends SQLiteOpenHelper {
private Context mContext;
//创建表SQL语句
public static final String CREATE_BOOK = "create table Book("
+"_id integer primary key autoincrement,"
+"author text,"
+"price real,"
+"pages integer,"
+"name text )";
// String stu_table="create table usertable(_id integer primary key autoincrement,sname text,snumber text)";
/**
* 构造函数
* @param context
* @param name
* @param factory
* @param version
*/
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
/**
* 创建数据库
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,"创建成功",Toast.LENGTH_SHORT).show();
}
/**
* 数据库升级
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.d("LUO","oldVersion============"+oldVersion);
Log.d("LUO","newVersion============"+newVersion);
}
}
2. 创建表
创建一张表的步骤很简单:
- 编写创建表的SQL语句
- 调用SQLiteDatabase的execSQL()方法来执行SQL语句
下面的代码创建了一张用户表,属性列为:id(主键并且自动增加)、sname(学生姓名)、snumber(学号)
private void createTable(SQLiteDatabase db){
//创建表SQL语句
String stu_table="create table usertable(_id integer primary key autoincrement,sname text,snumber text)";
//执行SQL语句
db.execSQL(stu_table);
}
3. 插入数据有两种方法:
①SQLiteDatabase的insert(String table,String nullColumnHack,ContentValues values)方法,
参数1 表名称,
参数2 空列的默认值
参数3 ContentValues类型的一个封装了列名称和列值的Map;
②编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行
第一种方法的代码:
private void insert(SQLiteDatabase db){
//实例化常量值
ContentValues cValue = new ContentValues();
//添加用户名
cValue.put("sname","xiaoming");
//添加密码
cValue.put("snumber","01005");
//调用insert()方法插入数据
db.insert("stu_table",null,cValue);
}
第二种方法的代码:
private void insert(SQLiteDatabase db){
//插入数据SQL语句
String stu_sql="insert into stu_table(sname,snumber) values('xiaoming','01005')";
//执行SQL语句
db.execSQL(sql);
}
4. 删除数据
删除数据也有两种方法:
①调用SQLiteDatabase的delete(String table,String whereClause,String[] whereArgs)方法
参数1 表名称
参数2 删除条件
参数3 删除条件值数组
②编写删除SQL语句,调用SQLiteDatabase的execSQL()方法来执行删除。
第一种方法的代码:
private void delete(SQLiteDatabase db) {
//删除条件
String whereClause = "id=?";
//删除条件参数
String[] whereArgs = {String.valueOf(2)};
//执行删除
db.delete("stu_table",whereClause,whereArgs);
}
第二种方法的代码:
private void delete(SQLiteDatabase db) {
//删除SQL语句
String sql = "delete from stu_table where _id = 6";
//执行SQL语句
db.execSQL(sql);
}
5. 更改数据
修改数据有两种方法:
①调用SQLiteDatabase的update(String table,ContentValues values,String whereClause, String[] whereArgs)方法
参数1 表名称
参数2 跟行列ContentValues类型的键值对Key-Value
参数3 更新条件(where字句)
参数4 更新条件数组
②编写更新的SQL语句,调用SQLiteDatabase的execSQL执行更新。
第一种方法的代码:
private void update(SQLiteDatabase db) {
//实例化内容值 ContentValues values = new ContentValues();
//在values中添加内容
values.put("snumber","101003");
//修改条件
String whereClause = "id=?";
//修改添加参数
String[] whereArgs={String.valuesOf(1)};
//修改
db.update("usertable",values,whereClause,whereArgs);
}
第二种方法的代码:
private void update(SQLiteDatabase db){
//修改SQL语句
String sql = "update stu_table set snumber = 654321 where id = 1";
//执行SQL
db.execSQL(sql);
}
6. 查询数据
在Android中查询数据是通过Cursor类来实现的,当我们使用SQLiteDatabase.query()方法时,会得到一个Cursor对象,Cursor指向的就是每一条数据。它提供了很多有关查询的方法,具体方法如下:
public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit);
各个参数的意义说明:
参数table:表名称
参数columns:列名称数组
参数selection:条件字句,相当于where
参数selectionArgs:条件字句,参数数组
参数groupBy:分组列
参数having:分组条件
参数orderBy:排序列
参数limit:分页查询限制
参数Cursor:返回值,相当于结果集ResultSet
Cursor是一个游标接口,提供了遍历查询结果的方法,如移动指针方法move(),获得列值方法getString()等.
Cursor游标常用方法
方法名称 | 方法描述 |
---|---|
getCount() | 获得总的数据项数 |
isFirst() | 判断是否第一条记录 |
isLast() | 判断是否最后一条记录 |
moveToFirst() | 移动到第一条记录 |
moveToLast() | 移动到最后一条记录 |
move(int offset) | 移动到指定记录 |
moveToNext() | 移动到下一条记录 |
moveToPrevious() | 移动到上一条记录 |
getColumnIndexOrThrow(String columnName) | 根据列名称获得列索引 |
getInt(int columnIndex) | 获得指定列索引的int类型值 |
getString(int columnIndex) | 获得指定列缩影的String类型值 |
下面就是用Cursor来查询数据库中的数据,具体代码如下:
private void query(SQLiteDatabase db) {
//查询获得游标
Cursor cursor = db.query ("usertable",null,null,null,null,null,null);
//判断游标是否为空
if(cursor.moveToFirst() {
//遍历游标
for(int i=0;i<cursor.getCount();i++){
cursor.move(i);
//获得ID
int id = cursor.getInt(0);
//获得用户名
String username=cursor.getString(1);
//获得密码
String password=cursor.getString(2);
//输出用户信息 System.out.println(id+":"+sname+":"+snumber);
}
}
}
7. 删除指定表
编写插入数据的SQL语句,直接调用SQLiteDatabase的execSQL()方法来执行
private void drop(SQLiteDatabase db){
//删除表的SQL语句
String sql ="DROP TABLE stu_table";
//执行SQL
db.execSQL(sql);
}
四、SQLiteOpenHelper介绍:
该类是SQLiteDatabase一个辅助类。这个类主要生成一 个数据库,并对数据库的版本进行管理。当在程序当中调用这个类的方法getWritableDatabase()或者 getReadableDatabase()方法的时候,如果当时没有数据,那么Android系统就会自动生成一个数据库。 SQLiteOpenHelper 是一个抽象类,我们通常需要继承它,并且实现里面的3个函数:
1. onCreate(SQLiteDatabase)
在数据库第一次生成的时候会调用这个方法,也就是说,只有在创建数据库的时候才会调用,当然也有一些其它的情况,一般我们在这个方法里边生成数据库表。
2. onUpgrade(SQLiteDatabase,int,int)
当数据库需要升级的时候,Android系统会主动的调用这个方法。一般我们在这个方法里边删除数据表,并建立新的数据表,当然是否还需要做其他的操作,完全取决于应用的需求。
3. onOpen(SQLiteDatabase):
这是当打开数据库时的回调函数,一般在程序中不是很常使用。
4. MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) :
必须要有构造函数
5. MainActivity类
public class MainActivity extends AppCompatActivity {
@BindView(R.id.insert)
Button insert;
@BindView(R.id.update)
Button update;
@BindView(R.id.delete)
Button delete;
@BindView(R.id.query)
Button query;
SQLiteDatabase dbHelper;
@BindView(R.id.et_content)
EditText etContent;
String inputStr;
@BindView(R.id.show)
TextView show;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
inputStr = etContent.getText().toString();
init();
}
private void init() {
//依靠DatabaseHelper带全部参数的构造函数创建数据库
MyDatabaseHelper db = new MyDatabaseHelper(MainActivity.this, "test_db", null, 1);
dbHelper = db.getWritableDatabase();
}
@OnClick({R.id.insert, R.id.update, R.id.delete, R.id.query})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.insert:
//创建存放数据的ContentValues对象
ContentValues values = new ContentValues();
values.put("author", "小明");
values.put("price", 33.33);
values.put("pages", "8");
values.put("name", "Android");
//数据库执行插入命令
dbHelper.insert("Book", null, values);
values.clear();
//第二组数据
values.put("author", "小刚");
values.put("price", 68.33);
values.put("pages", "88");
values.put("name", "Java");
//数据库执行插入命令
dbHelper.insert("Book", null, values);
break;
case R.id.update:
ContentValues values2 = new ContentValues();
values2.put("name", "小刚");
dbHelper.update("Book", values2, "name = ?", new String[]{"小赵"});
break;
case R.id.delete:
dbHelper.delete("Book", "name=?", new String[]{inputStr});
break;
case R.id.query:
//创建游标对象
Cursor cursor = dbHelper.query("Book", new String[]{"name,author,price,pages"}, null, null, null, null, null);
//利用游标遍历所有数据对象
//为了显示全部,把所有对象连接起来,放到TextView中
String textview_data = "";
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String author = cursor.getString(cursor.getColumnIndex("author"));
String pages = cursor.getString(cursor.getColumnIndex("pages"));
String price = cursor.getString(cursor.getColumnIndex("price"));
textview_data = textview_data + "\n" + name+ "\n" +author+ "\n" +pages+ "\n" +price;
}
show.setText(textview_data);
// 关闭游标,释放资源
cursor.close();
break;
default:
break;
}
}
}
6. activity_main.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.function.luo.sqlitedemo.MainActivity"
android:orientation="vertical"
>
<EditText
android:id="@+id/et_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入内容"
/>
<Button
android:id="@+id/insert"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="插入数据"
/>
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="更新数据"
/>
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="删除数据"
/>
<Button
android:id="@+id/query"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="查询数据"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="展示结果:"
/>
<TextView
android:id="@+id/show"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="~"
android:textColor="#FF0000"
android:textSize="20dp"
/>
</LinearLayout>
参考:https://www.runoob.com/sqlite/sqlite-create-table.html
参考:https://www.cnblogs.com/foxy/p/7725010.html
参考:https://blog.csdn.net/midnight_time/article/details/80834198