1.SQLite数据类型简介
SQLite 数据类型是一个用来指定任何对象的数据类型的属性。SQLite 中的每一列,每个变量和表达式都有相关的数据类型。
您可以在创建表的同时使用这些数据类型。SQLite 使用一个更普遍的动态类型系统。在 SQLite 中,值的数据类型与值本身是相关的,而不是与它的容器相关。
2.SQLite 存储类
每个存储在 SQLite 数据库中的值都具有以下存储类之一
3.SQLite 亲和(Affinity)类型
SQLite支持列的亲和类型概念。任何列仍然可以存储任何类型的数据,当数据插入时,该字段的数据将会优先采用亲缘类型作为该值的存储方式。SQLite目前的版本支持以下五种亲缘类型:
4.SQLite 亲和类型(Affinity)及类型名称
下表列出了当创建 SQLite3 表时可使用的各种数据类型名称,同时也显示了相应的亲和类型:
5.Boolean 数据类型
SQLite 没有单独的 Boolean 存储类。相反,布尔值被存储为整数 0(false)和 1(true)。
6.Date 与 Time 数据类型
SQLite 没有一个单独的用于存储日期和/或时间的存储类,但 SQLite 能够把日期和时间存储为 TEXT、REAL 或 INTEGER 值。
7.char、varchar、text和nchar、nvarchar、ntext的区别
1、CHAR。CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充。
2、VARCHAR。存储变长数据,但存储效率没有CHAR高。如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。为什么“+1”呢?这一个字节用于保存实际使用了多大的长度。从空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。
3、TEXT。text存储可变长度的非Unicode数据,最大长度为2^31-1(2,147,483,647)个字符。
4、NCHAR、NVARCHAR、NTEXT。这三种从名字上看比前面三种多了个“N”。它表示存储的是Unicode数据类型的字符。我们知道字符中,英文字符只需要一个字节存储就足够了,但汉字众多,需要两个字节存储,英文与汉字同时存在时容易造成混乱,Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示。nchar、nvarchar的长度是在1到4000之间。和char、varchar比较起来,nchar、nvarchar则最多存储4000个字符,不论是英文还是汉字;而char、varchar最多能存储8000个英文,4000个汉字。可以看出使用nchar、nvarchar数据类型时不用担心输入的字符是英文还是汉字,较为方便,但在存储英文时数量上有些损失。
所以一般来说,如果含有中文字符,用nchar/nvarchar,如果纯英文和数字,用char/varchar。
8.SQLite数据库有点
SQLite最大的特点在于其数据类型为无数据类型(typelessness)。这意味着可以保存任何类型的数据到所想要保存的任何表的任何列中,无论这列声明的数据类型是什么。虽然在生成表结构的时候,要声明每个域的数据类型,但SQLite并不做任何检查。开发人员要靠自己的程序来控制输入与读出数据的类型。这里有一个例外,就是当主键为整型值时,如果要插入一个非整型值时会产生异常。虽然,SQLite允许忽略数据类型,但是,仍然建议在Create Table语句中指定数据类型,因为数据类型有利于增强程序的可读性。另外,虽然在插入或读出数据的时候是不区分类型的,但在比较的时候,不同数据类型是有区别的。
代码
SQLiteOpenHelper实现类代码
package com.wjn.androiddbdemo.utils.db;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* SQLiteOpenHelper实现类
* */
public class SQLiteHelp extends SQLiteOpenHelper {
/**
* 构造方法
* */
public SQLiteHelp(Context context, String name, SQLiteDatabase.CursorFactory factory,int version) {
super(context, name, factory, version);
}
/**
* onCreate方法
* 首次使用软件时生成数据库表
* */
@Override
public void onCreate(SQLiteDatabase db) {
String sql = "create table user(id int,name varchar(20))";
db.execSQL(sql);
}
/**
* onUpgrade方法
* 在数据库的版本发生变化时会被调用, 一般在软件升级时才需改变版本号
* 将老表的数据复制到新表
* */
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//1.将旧表改名成临时表
String sql1 = "ALTER TABLE user RENAME TO _temp_User";
//2.创建新表
String sql2=" CREATE TABLE user (id int,name varchar(20),describe varchar(200));";
//3.将临时表的数据导入到新表 原表中没有的要自己设个默认值
String sql3="INSERT INTO User SELECT id,name,\"这是描述\" FROM _temp_User";
//删除临时表
String sql4="DROP TABLE _temp_User";
//执行SQL语句
db.execSQL(sql1);
db.execSQL(sql2);
db.execSQL(sql3);
db.execSQL(sql4);
}
}
Activity代码
package com.wjn.androiddbdemo.activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;
import com.wjn.androiddbdemo.R;
import com.wjn.androiddbdemo.utils.db.SQLiteHelp;
import com.wjn.androiddbdemo.utils.ui.StatusBarUtil;
public class SimpleSQLiteActivity extends AppCompatActivity implements View.OnClickListener {
private TextView textView1;
private TextView textView2;
private TextView textView3;
private TextView textView4;
private TextView textView5;
private TextView textView6;
private TextView textView7;
private TextView textView8;
private TextView textView;
private SQLiteHelp dbHelp;//帮助类对象
private SQLiteDatabase db;//用于管理和操作SQLite数据库
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simplesqlite);
initView();
}
/**
* 初始化各种View
*/
private void initView() {
//根据状态栏颜色来决定 状态栏背景 用黑色还是白色 true:是否修改状态栏字体颜色
StatusBarUtil.setStatusBarMode(this, false, false, R.color.colorPrimary);
textView1 = findViewById(R.id.activity_simplesqlite_textview1);
textView2 = findViewById(R.id.activity_simplesqlite_textview2);
textView3 = findViewById(R.id.activity_simplesqlite_textview3);
textView4 = findViewById(R.id.activity_simplesqlite_textview4);
textView5 = findViewById(R.id.activity_simplesqlite_textview5);
textView6 = findViewById(R.id.activity_simplesqlite_textview6);
textView7 = findViewById(R.id.activity_simplesqlite_textview7);
textView8 = findViewById(R.id.activity_simplesqlite_textview8);
textView = findViewById(R.id.activity_simplesqlite_textview);
textView1.setOnClickListener(this);
textView2.setOnClickListener(this);
textView3.setOnClickListener(this);
textView4.setOnClickListener(this);
textView5.setOnClickListener(this);
textView6.setOnClickListener(this);
textView7.setOnClickListener(this);
textView8.setOnClickListener(this);
dbHelp = new SQLiteHelp(this, "Test.db", null, 1);
}
/**
* 各种点击事件的方法
*/
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.activity_simplesqlite_textview1://API语句 增
insertbtnMethod();
break;
case R.id.activity_simplesqlite_textview2://API语句 删
delbtnMethod();
break;
case R.id.activity_simplesqlite_textview3://API语句 改
updatebtnMethod();
break;
case R.id.activity_simplesqlite_textview4://API语句 查
findbtnMethod();
break;
case R.id.activity_simplesqlite_textview5://SQLite语句 增
insertbtnMethods();
break;
case R.id.activity_simplesqlite_textview6://SQLite语句 删
delbtnMethods();
break;
case R.id.activity_simplesqlite_textview7://SQLite语句 改
updatebtnMethods();
break;
case R.id.activity_simplesqlite_textview8://SQLite语句 查
findbtnMethods();
break;
default:
break;
}
}
/**
* API语句 增
*/
public void insertbtnMethod() {
//打开数据库
db = dbHelp.getReadableDatabase();
//插入一条数据
ContentValues values1 = new ContentValues();//类似于map
values1.put("id", 1);
values1.put("name", "张三");
db.insert("user", null, values1);
//插入一条数据
ContentValues values2 = new ContentValues();
values2.put("id", 2);
values2.put("name", "李四");
db.insert("user", null, values2);
//插入一条数据
ContentValues values3 = new ContentValues();//类似于map
values3.put("id", 3);
values3.put("name", "王五");
db.insert("user", null, values3);
//插入一条数据
ContentValues values4 = new ContentValues();
values4.put("id", 4);
values4.put("name", "赵六");
db.insert("user", null, values4);
//关闭数据库
db.close();
}
/**
* API语句 删
*/
public void delbtnMethod() {
//打开数据库
db = dbHelp.getReadableDatabase();
//执行删除操作
db.delete("user", "id=3", null);
//关闭数据库
db.close();
}
/**
* API语句 改
*/
public void updatebtnMethod() {
//打开数据库
db = dbHelp.getReadableDatabase();
//类似于map
ContentValues values = new ContentValues();
values.put("name", "API修改");
db.update("user", values, "id=1", null);
//关闭数据库
db.close();
}
/**
* API语句 查
*/
public void findbtnMethod() {
db = dbHelp.getReadableDatabase();//打开数据库对象
Cursor cursor = db.query("user", null, null, null, null, null, null);
//遍历游标对象
cursor.moveToFirst();
StringBuilder sb = new StringBuilder();
while (!cursor.isAfterLast()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
sb.append("ID:" + id + "\n");
String name = cursor.getString(cursor.getColumnIndex("name"));
sb.append("姓名:" + name + "\n\n");
cursor.moveToNext();
}
textView.setText(sb.toString());
db.close();
}
/**
* SQL语句 增
* */
public void insertbtnMethods() {
//打开数据库
db = dbHelp.getReadableDatabase();
//SQL语句
String sql1 = "insert into user values(1,'张三')";
String sql2 = "insert into user values(2,'李四')";
String sql3 = "insert into user values(3,'王五')";
String sql4 = "insert into user values(4,'赵六')";
db.execSQL(sql1);
db.execSQL(sql2);
db.execSQL(sql3);
db.execSQL(sql4);
//关闭数据库
db.close();
}
/**
* SQL语句 删
* */
public void delbtnMethods() {
//打开数据库
db = dbHelp.getReadableDatabase();
//SQL语句
String sql = "delete from user where id=1";
db.execSQL(sql);
//关闭数据库
db.close();
}
/**
* SQL语句 改
* */
public void updatebtnMethods() {
//打开数据库
db = dbHelp.getReadableDatabase();
//SQL语句
String sql = "update user set name='SQL修改' where id=2";
db.execSQL(sql);
//关闭数据库
db.close();
}
/**
* SQL语句 查
* */
public void findbtnMethods() {
//打开数据库
db = dbHelp.getReadableDatabase();
//SQL语句
String sql = "select * from user";
Cursor cursor = db.rawQuery(sql, null);
cursor.moveToFirst();
StringBuilder sbBuilder = new StringBuilder();
while (!cursor.isAfterLast()) {
int id = cursor.getInt(cursor.getColumnIndex("id"));
sbBuilder.append("ID:" + id + "\n");
String name = cursor.getString(cursor.getColumnIndex("name"));
sbBuilder.append("姓名:" + name + "\n\n");
cursor.moveToNext();
}
textView.setText(sbBuilder.toString());
//关闭数据库
db.close();
}
}
结果
API语句 增—>查
API语句 删—>查
API语句 改—>查
SQL语句 增—>查
SQL语句 删—>查
SQL语句 改—>查
Android使用getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。(getReadableDatabase()方法中会调用getWritableDatabase()方法)
其中getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用的是getWritableDatabase() 方法就会出错。
getReadableDatabase()方法则是先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。如果该问题成功解决,则只读数据库对象就会关闭,然后返回一个可读写的数据库对象。
getWritableDatabase源码
public synchronized SQLiteDatabase getWritableDatabase() {
if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) {
throw new IllegalStateException("getWritableDatabase called recursively");
}
boolean success = false;
SQLiteDatabase db = null;
if (mDatabase != null) mDatabase.lock();
try {
mIsInitializing = true;
if (mName == null) {
db = SQLiteDatabase.create(null);
} else {
db = mContext.openOrCreateDatabase(mName, 0, mFactory);
}
int version = db.getVersion();
if (version != mNewVersion) {
db.beginTransaction();
try {
if (version == 0) {
onCreate(db);
} else {
onUpgrade(db, version, mNewVersion);
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
onOpen(db);
success = true;
return db;
} finally {
mIsInitializing = false;
if (success) {
if (mDatabase != null) {
try { mDatabase.close(); } catch (Exception e) { }
mDatabase.unlock();
}
mDatabase = db;
} else {
if (mDatabase != null) mDatabase.unlock();
if (db != null) db.close();
}
}
}
getReadableDatabase源码
public synchronized SQLiteDatabase getReadableDatabase() {
if (mDatabase != null && mDatabase.isOpen()) {
return mDatabase; // The database is already open for business
}
if (mIsInitializing) {
throw new IllegalStateException("getReadableDatabase called recursively");
}
try {
return getWritableDatabase();
} catch (SQLiteException e) {
if (mName == null) throw e; // Can't open a temp database read-only!
}
SQLiteDatabase db = null;
try {
mIsInitializing = true;
String path = mContext.getDatabasePath(mName).getPath();
db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);
if (db.getVersion() != mNewVersion) {
throw new SQLiteException("Can't upgrade read-only database from version " +
db.getVersion() + " to " + mNewVersion + ": " + path);
}
onOpen(db);
Log.w(TAG, "Opened " + mName + " in read-only mode");
mDatabase = db;
return mDatabase;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) db.close();
}
}
代码链接:https://github.com/wujianning/AndroidDBDemo