1.简介
2.SQLiteOpenHelper类 常用方法
1. 创建 or 打开 可读/写的数据库(通过 返回的SQLiteDatabase对象 进行操作)
getWritableDatabase()
2. 创建 or 打开 可读的数据库(通过 返回的SQLiteDatabase对象 进行操作)
getReadableDatabase()
3. 数据库第1次创建时 则会调用,即 第1次调用 getWritableDatabase() / getReadableDatabase()时调用(在继承 SQLiteOpenHelper类的子类中复写)
onCreate(SQLiteDatabase db)
4. 数据库升级时自动调用(在继承SQLiteOpenHelper类的子类中复写)
onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
5. 关闭数据库
close()
3 . 数据库操作(增、删、减、查)
1. 查询数据
(Cursor) query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having,
String orderBy, String limit) 查询指定的数据表返回一个带游标的数据集。
参数说明:
table:表名称
colums:列名称数组
selection:条件子句,相当于where
selectionArgs:条件语句的参数数组
groupBy:分组
having:分组条件
orderBy:排序类
limit:分页查询的限制
Cursor:返回值,相当于结果集ResultSet
(Cursor) rawQuery(String sql, String[] selectionArgs) 运行一个预置的SQL语句,返回带游标的数据集(与上面的语句最大的
区别 = 防止SQL注入)
2. 删除数据行
(int) delete(String table,String whereClause,String[] whereArgs)
3. 添加数据行
(long) insert(String table,String nullColumnHack,ContentValues values)
4. 更新数据行
(int) update(String table, ContentValues values, String whereClause, String[] whereArgs)
5. 执行一个SQL语句,可以是一个select or 其他sql语句 即 直接使用String类型传入sql语句 & 执行
(void) execSQL(String sql)
4.数据库的创建表时,字段的数据类型
字段的数据类型:整数类型,浮点类型,日期类型,字符串类型,枚举类型与集合类型
1. 整数类型: int
2. 浮点类型:float double decimal
3. 日期类型 YEAR DATE TIME DATETIME TIMESTAMP
作用:存储用户注册时间,文章发布时间等
规则:
YEAR
YYYY(1901/2155)
DATE
YYYY-MM-DD(1000-01-01/9999-12-31)
TIME
HH:MM:SS('-838:59:59'/'838:59:59')
DATETIME
YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59 Y)
TIMESTAMP
YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某时)
示例:create table t11(d date,t time,dt datetime);
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| d | date | YES | | NULL | |
| t | time | YES | | NULL | |
| dt | datetime | YES | | NULL | |
+-------+----------+------+-----+---------+-------+
datetime与timestamp的区别:
DATETIME的日期范围是1001——9999年,TIMESTAMP的时间范围是1970——2038年。
DATETIME使用8字节的存储空间,TIMESTAMP的存储空间为4字节。因此,TIMESTAMP空间利用率更高。
DATETIME的默认值为null;TIMESTAMP的字段默认不为空(notnull),默认值为当前时间
4. 字符串类型:char和varchar括号内的参数指的都是字符的长度
1.char类型:定长,浪费空间,存取速度快
字符长度范围:0-255(一个中文是一个字符,是utf8编码的3个字节)
存储:
存储char类型的值时,按指定宽度存,不够右填充空格,
所以定长检索速度快,定长的宽度去解析。
例如:指定长度为10,存>10个字符则报错,存<10个字符则用空格填充直到凑够10个字符存储
检索:
在检索或者说查询时,查出的结果显示时,会自动删除尾部的空格,除非我们打开
pad_char_to_full_length SQL模式(SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';)
2.varchar类型:变长,精准,节省空间,存取速度慢,字符长度范围:0-65535(如果大于21845会提
示用其他类型 。mysql行最大限制为65535字节,字符编码为utf-8:
存储:
varchar类型存储数据的真实内容,不会用空格填充,如果'ab ',尾部的空格也会被存起来,
但是:varchar类型会在真实数据前加1-2Bytes的前缀,
表示真实数据的bytes字节数,检索的时候才知道检索多少。
如果真实的数据<255bytes则需要1Bytes的前缀(1Bytes=8bit 2**8最大表示的数字为255)
如果真实的数据>255bytes则需要2Bytes的前缀(2Bytes=16bit 2**16最大表示的数字为65535)
检索:
尾部有空格会保存下来,在查询时,正常显示包含空格在内的内容
#其他字符串系列(效率:char>varchar>text)
TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT
BLOB 系列 TINYBLOB BLOB MEDIUMBLOB LONGBLOB
BINARY系列 BINARY VARBINARY
5.约束条件
1.primary key 标识该字段为该表的主键,可以唯一的标识记录
主键,存储引擎innodb一张表必须有主键,不指定会自动检索不为空且唯一的字段创建,检索不到会创建一个隐藏字段。建表时指定主键。
通常一张表,都应该有一个id字段用来标识记录编号,id通常设置为主键。
一个表内只能有一个主键primary key
=not null unique 不为空且唯一
单列做主键:不为空且唯一;常用。
多列做主键(复合主键):多个字段连在一起,当作主键;
create table department2(
id int primary key, #主键
name varchar(20),
comment varchar(100)
);
2.foreign key 标识该字段为该表的外键
外键,建立表与表之间的关系。
表类型必须是innodb存储引擎,且被关联的字段,即references指定的另外一个表的字段,必须保证唯一
语法:foreign key(dep_id) references dep(id)
最好不要用外键建立硬性关系,以后修改比较麻烦。
先建被关联的表,并且保证被关联的字段唯一
create table dep(
id int primary key,
name char(16),
comment char(50)
);
#再建立关联的表
create table emp(
id int primary key,
name char(10),
sex enum('male','female'),
dep_id int,
foreign key(dep_id) references dep(id)
on delete cascade #如果没有,删除时候不能先删被关联的,也不能先更改被关联的。
on update cascade # 被关联的有更新或者删除都会关联,没有逗号
);
#先往被关联表插入记录
insert into dep values
#再往关联表插入记录
insert into emp values
3. not null 标识该字段不能为空
4. unique 标识该字段的值是唯一的
5. auto_increment 标识该字段的值自动增长(整数类型,而且为主键)
6. default 为该字段设置默认值
7. unsigend 无符号
8. zerofill 使用0填充
6. 自定义数据库实现类(继承 SQLiteOpenHelper 类)
SQLiteOpenHelper 类
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
private static final String TAG = MySQLiteOpenHelper.class.getSimpleName();
//数据库版本号
private static Integer Version = 1;
private Context mContext;
public MySQLiteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
// 参数说明
// context:上下文对象
// name:数据库名称
// param:一个可选的游标工厂(通常是 Null)
// version:当前数据库的版本,值必须是整数并且是递增的状态
// 必须通过super调用父类的构造函数
super(context, name, factory, version);
mContext=context;
}
public MySQLiteOpenHelper( Context context, String name,int Version){
this(context, name, null,Version);
}
public MySQLiteOpenHelper( Context context, String name){
this(context, name, Version);
}
/**
* 复写onCreate()
* 调用时刻:当数据库第1次创建时调用
* 作用:创建数据库 表 & 初始化数据
* SQLite数据库创建支持的数据类型: 整型数据、字符串类型、日期类型、二进制
*/
@Override
public void onCreate(SQLiteDatabase db) {
//拼接sql语句
//create table user 创建user表
//id int primary key 创建一个id 字段数据类型为整形,且id唯一
//name varchar(200) 创建一个name字段 数据类型为字符串类型,长度为200
//age integer 创建一个age字段 数据类型为整数类型
//path text 创建一个path字段 数据类型为字符串类型
String sql ="create table user(id int primary key ,name varchar(200),age integer,path text )";
//execSQL用于执行SQL语句,完成数据库的创建
db.execSQL(sql);
}
/***
* 数据库升级时调用
* 如果VERSION值被改为2,系统发现现有数据库版本不同,即会调用onUpgrade()方法
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.e(TAG,"更新数据库版本为:"+newVersion);
}
}
7.创建数据库
// 步骤1:创建DatabaseHelper对象
// 注:此时还未创建数据库
MySQLiteOpenHelper dbHelper1 = new MySQLiteOpenHelper(this,"test_db",1);
// 步骤2:真正创建 / 打开数据库
SQLiteDatabase sqliteDatabase = dbHelper.getWritableDatabase(); // 创建 or 打开 可读/写的数据库
SQLiteDatabase sqliteDatabase = dbHelper.getReadableDatabase(); // 创建 or 打开 可读的数据库
对于操作 = “增、删、改(更新)”,需获得 可"读 / 写"的权限:getWritableDatabase()
对于操作 = “查询”,需获得 可"读 "的权限getReadableDatabase()
8 操作数据库(增、删、查、改)
//点击创建数据库库
case R.id.instablish:
// 创建SQLiteOpenHelper子类对象
MySQLiteOpenHelper text_db = new MySQLiteOpenHelper(this, "text_db");
//数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开
SQLiteDatabase writableDatabase = text_db.getWritableDatabase();
MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this,"test_db");
break;
//点击更新数据
case R.id.upgrade:
//将版本号变大且是整数形式
MySQLiteOpenHelper dbHelper_upgrade = new MySQLiteOpenHelper(this,"text_db",2);
break;
//点击插入数据到数据库
case R.id.insert:
Toast.makeText(this,"插入数据库",Toast.LENGTH_SHORT).show();
// 创建SQLiteOpenHelper子类对象
MySQLiteOpenHelper dbHelper1 = new MySQLiteOpenHelper(this,"test_db",1);
SQLiteDatabase sqliteDatabase1 = dbHelper1.getWritableDatabase();
for (int i = 0; i < 10; i++) {
// 创建ContentValues对象
ContentValues contentValues = new ContentValues();
//其中,key = 列名,value = 插入的值
contentValues.put("name","张三"+i);
contentValues.put("age",i);
contentValues.put("id",i);
contentValues.put("path","www.baidu.com");
// 调用insert()方法将数据插入到数据库当中
// 参数1:要操作的表名称
// 参数2:SQl不允许一个空列,若ContentValues是空,那么这一列被明确的指明空字符串
// 参数3:ContentValues对象
sqliteDatabase1.insert("user","",contentValues);
}
//关闭数据库
sqliteDatabase1.close();
break;
//点击查询数据库中所有数据
case R.id.query:
Toast.makeText(this,"查询数据库",Toast.LENGTH_SHORT).show();
// 创建DatabaseHelper对象
MySQLiteOpenHelper dbHelper4 = new MySQLiteOpenHelper(MainActivity.this,"test_db",1);
SQLiteDatabase sqliteDatabase4 = dbHelper4.getReadableDatabase();
// 调用SQLiteDatabase对象的query方法进行查询
// 返回一个Cursor对象:由数据库查询返回的结果集对象
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having,
// String orderBy)
// 参数说明
// table:要操作的表
// columns:查询的列所有名称集
// selection:WHERE之后的条件语句,可以使用占位符
// groupBy:指定分组的列名
// having指定分组条件,配合groupBy使用
// orderBy指定排序的列名
// limit指定分页参数
// distinct可以指定“true”或“false”表示要不要过滤重复值
// 所有方法将返回一个Cursor对象,代表数据集的游标
Cursor cursor = sqliteDatabase4.query("user", new String[] {
"name" ,"age","path","id"}, null/*"id=?"*/,null /*new String[] { "1" }*/, null, null, null);
String name = null;
int age ;
int id ;
String path = null;
//将光标移动到下一行,从而判断该结果集是否还有下一条数据
//如果有则返回true,没有则返回false
/* //Cursor对象常用方法如下:
c.move(int offset); //以当前位置为参考,移动到指定行
c.moveToFirst(); //移动到第一行
c.moveToLast(); //移动到最后一行
c.moveToPosition(int position); //移动到指定行
c.moveToPrevious(); //移动到前一行
c.moveToNext(); //移动到下一行
c.isFirst(); //是否指向第一条
c.isLast(); //是否指向最后一条
c.isBeforeFirst(); //是否指向第一条之前
c.isAfterLast(); //是否指向最后一条之后
c.isNull(int columnIndex); //指定列是否为空(列基数为0)
c.isClosed(); //游标是否已关闭
c.getCount(); //总数据项数
c.getPosition(); //返回当前游标所指向的行数
c.getColumnIndex(String columnName);//返回某列名对应的列索引值
c.getString(int columnIndex); //返回当前行指定列的值 */
while (cursor.moveToNext()) {
id = cursor.getInt(cursor.getColumnIndex("id"));
age = cursor.getInt(cursor.getColumnIndex("age"));
name = cursor.getString(cursor.getColumnIndex("name"));
path = cursor.getString(cursor.getColumnIndex("path"));
//输出查询结果
Log.e("MainActivity","查询到的数据是: "+"name: "+name+"age: "+age+" "+"path: "+path);
}
//关闭数据库
sqliteDatabase4.close();
break;
//点击修改数据
case R.id.modify:
Toast.makeText(this,"修改数据",Toast.LENGTH_SHORT).show();
// 创建一个DatabaseHelper对象
// 将数据库的版本升级为2
// 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库
MySQLiteOpenHelper dbHelper2 = new MySQLiteOpenHelper(MainActivity.this,"test_db", 1);
// 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象
SQLiteDatabase sqliteDatabase2 = dbHelper2.getWritableDatabase();
// 创建一个ContentValues对象
ContentValues values2 = new ContentValues();
values2.put("name", "王五");
// 调用update方法修改数据库 //更新条件 修改表user 中 id=1 这一行中的name数据修改成zhangsan
sqliteDatabase2.update("user", values2, "id=?", new String[]{"1"});
//关闭数据库
sqliteDatabase2.close();
break;
//点击删除数据
case R.id.delete:
Toast.makeText(this,"删除数据",Toast.LENGTH_SHORT).show();
// 创建DatabaseHelper对象
MySQLiteOpenHelper dbHelper3 = new MySQLiteOpenHelper(MainActivity.this,"test_db",1);
// 调用getWritableDatabase()方法创建或打开一个可以读的数据库
SQLiteDatabase sqliteDatabase3 = dbHelper3.getWritableDatabase();
//删除数据
sqliteDatabase3.delete("user", "id=?", new String[]{"1"});
//关闭数据库
sqliteDatabase3.close();
break;
//点击删除数据库
case R.id.delete_database:
Toast.makeText(this,"删除数据库",Toast.LENGTH_SHORT).show();
//删除名为test.db数据库
deleteDatabase("test_db");
break;
default:
break;
9实例代码如下:
MainActivity 类 :按顺序点击:创建 - 插入 - 查询 - 修改 - 查询 - 删除数据- 更新
/***
* SQLiteOpenHelper的使用
*
*/
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button instablish;
private Button insert;
private Button upgrade;
private Button modify;
private Button delete;
private Button query;
private Button delete_database;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
instablish = (Button) findViewById(R.id.instablish);
insert = (Button) findViewById(R.id.insert);
upgrade = (Button) findViewById(R.id.upgrade);
modify = (Button) findViewById(R.id.modify);
delete = (Button) findViewById(R.id.delete);
query = (Button) findViewById(R.id.query);
delete_database = (Button) findViewById(R.id.delete_database);
//设置监听器
instablish.setOnClickListener(this);
insert.setOnClickListener(this);
upgrade.setOnClickListener(this);
modify.setOnClickListener(this);
delete.setOnClickListener(this);
query.setOnClickListener(this);
delete_database.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//点击创建数据库库
case R.id.instablish:
// 创建SQLiteOpenHelper子类对象
MySQLiteOpenHelper text_db = new MySQLiteOpenHelper(this, "text_db");
//数据库实际上是没有被创建或者打开的,直到getWritableDatabase() 或者 getReadableDatabase() 方法中的一个被调用时才会进行创建或者打开
SQLiteDatabase writableDatabase = text_db.getWritableDatabase();
MySQLiteOpenHelper dbHelper = new MySQLiteOpenHelper(this,"test_db");
break;
//点击更新数据
case R.id.upgrade:
//将版本号变大且是整数形式
MySQLiteOpenHelper dbHelper_upgrade = new MySQLiteOpenHelper(this,"text_db",2);
break;
//点击插入数据到数据库
case R.id.insert:
Toast.makeText(this,"插入数据库",Toast.LENGTH_SHORT).show();
// 创建SQLiteOpenHelper子类对象
MySQLiteOpenHelper dbHelper1 = new MySQLiteOpenHelper(this,"test_db",1);
SQLiteDatabase sqliteDatabase1 = dbHelper1.getWritableDatabase();
for (int i = 0; i < 10; i++) {
// 创建ContentValues对象
ContentValues contentValues = new ContentValues();
//其中,key = 列名,value = 插入的值
contentValues.put("name","张三"+i);
contentValues.put("age",i);
contentValues.put("id",i);
contentValues.put("path","www.baidu.com");
// 调用insert()方法将数据插入到数据库当中
// 参数1:要操作的表名称
// 参数2:SQl不允许一个空列,若ContentValues是空,那么这一列被明确的指明空字符串
// 参数3:ContentValues对象
sqliteDatabase1.insert("user","",contentValues);
}
//关闭数据库
sqliteDatabase1.close();
break;
//点击查询数据库中所有数据
case R.id.query:
Toast.makeText(this,"查询数据库",Toast.LENGTH_SHORT).show();
// 创建DatabaseHelper对象
MySQLiteOpenHelper dbHelper4 = new MySQLiteOpenHelper(MainActivity.this,"test_db",1);
SQLiteDatabase sqliteDatabase4 = dbHelper4.getReadableDatabase();
// 调用SQLiteDatabase对象的query方法进行查询
// 返回一个Cursor对象:由数据库查询返回的结果集对象
// query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having,
// String orderBy)
// 参数说明
// table:要操作的表
// columns:查询的列所有名称集
// selection:WHERE之后的条件语句,可以使用占位符
// groupBy:指定分组的列名
// having指定分组条件,配合groupBy使用
// orderBy指定排序的列名
// limit指定分页参数
// distinct可以指定“true”或“false”表示要不要过滤重复值
// 所有方法将返回一个Cursor对象,代表数据集的游标
Cursor cursor = sqliteDatabase4.query("user", new String[] {
"name" ,"age","path","id"}, null/*"id=?"*/,null /*new String[] { "1" }*/, null, null, null);
String name = null;
int age ;
int id ;
String path = null;
//将光标移动到下一行,从而判断该结果集是否还有下一条数据
//如果有则返回true,没有则返回false
/* //Cursor对象常用方法如下:
c.move(int offset); //以当前位置为参考,移动到指定行
c.moveToFirst(); //移动到第一行
c.moveToLast(); //移动到最后一行
c.moveToPosition(int position); //移动到指定行
c.moveToPrevious(); //移动到前一行
c.moveToNext(); //移动到下一行
c.isFirst(); //是否指向第一条
c.isLast(); //是否指向最后一条
c.isBeforeFirst(); //是否指向第一条之前
c.isAfterLast(); //是否指向最后一条之后
c.isNull(int columnIndex); //指定列是否为空(列基数为0)
c.isClosed(); //游标是否已关闭
c.getCount(); //总数据项数
c.getPosition(); //返回当前游标所指向的行数
c.getColumnIndex(String columnName);//返回某列名对应的列索引值
c.getString(int columnIndex); //返回当前行指定列的值 */
while (cursor.moveToNext()) {
id = cursor.getInt(cursor.getColumnIndex("id"));
age = cursor.getInt(cursor.getColumnIndex("age"));
name = cursor.getString(cursor.getColumnIndex("name"));
path = cursor.getString(cursor.getColumnIndex("path"));
//输出查询结果
Log.e("MainActivity","查询到的数据是: "+"name: "+name+"age: "+age+" "+"path: "+path);
}
//关闭数据库
sqliteDatabase4.close();
break;
//点击修改数据
case R.id.modify:
Toast.makeText(this,"修改数据",Toast.LENGTH_SHORT).show();
// 创建一个DatabaseHelper对象
// 将数据库的版本升级为2
// 传入版本号为2,大于旧版本(1),所以会调用onUpgrade()升级数据库
MySQLiteOpenHelper dbHelper2 = new MySQLiteOpenHelper(MainActivity.this,"test_db", 1);
// 调用getWritableDatabase()得到一个可写的SQLiteDatabase对象
SQLiteDatabase sqliteDatabase2 = dbHelper2.getWritableDatabase();
// 创建一个ContentValues对象
ContentValues values2 = new ContentValues();
values2.put("name", "王五");
// 调用update方法修改数据库 //更新条件 修改表user 中 id=1 这一行中的name数据修改成zhangsan
sqliteDatabase2.update("user", values2, "id=?", new String[]{"1"});
//关闭数据库
sqliteDatabase2.close();
break;
//点击删除数据
case R.id.delete:
Toast.makeText(this,"删除数据",Toast.LENGTH_SHORT).show();
// 创建DatabaseHelper对象
MySQLiteOpenHelper dbHelper3 = new MySQLiteOpenHelper(MainActivity.this,"test_db",1);
// 调用getWritableDatabase()方法创建或打开一个可以读的数据库
SQLiteDatabase sqliteDatabase3 = dbHelper3.getWritableDatabase();
//删除数据
sqliteDatabase3.delete("user", "id=?", new String[]{"1"});
//关闭数据库
sqliteDatabase3.close();
break;
//点击删除数据库
case R.id.delete_database:
Toast.makeText(this,"删除数据库",Toast.LENGTH_SHORT).show();
//删除名为test.db数据库
deleteDatabase("test_db");
break;
default:
break;
}
}
}