文章目录

  • 一、概念
    • 1、了解
    • 2、应用场景
  • 二、数据库操作
    • 1、创建数据库
    • 2、数据操作(增删改查)
      • 2.1 添加语句
        • 方法1:
        • 方法2:
      • 2.2 删除语句
      • 2.3 更新语句
      • 2.4 查询语句
    • 3、手机数据库文件的导入
      • ①在模拟机上
      • ②在真机上
  • ==疑问:mnt/adcard和storage/sdcard的区别?==
  • 三、在Android中对SQLite的使用
    • 1、界面布局
    • 2、SQLiteOpenHelper类
    • 3、SQLiteDatabase类
      • 使用到rawQuery() 、execSQL()
      • 3.1 创建表
      • 3.2 添加数据
      • 3.2 查询数据
      • 3.3 删除数据
      • 3.4 修改数据
      • 3.5 改进
      • 3.6 完整代码
  • 四、通过Android的API对SqLite数据库进行操作
    • 1、添加insert
    • 2、查询query
    • 3、删除delete
    • 4、修改update
    • 5、完整代码
  • 五、SQLite总结
  • 六、数据库操作的封装
    • 1、添加操作
    • 2、查询操作
    • 3、删除操作
    • 4、修改操作
    • 5、小结

一、概念

1、了解



2、应用场景

现在的主流移动设备像 Android、iPhone 等都使用 SQLite 作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到 SQLite 来存储我们大量的数据,所以我们就需要掌握移动设备上的 SQLite 开发技巧。对于 Android 平台来说, 系统内置了丰富的 API 来供开发人员操作 SQLite,我们可以轻松的完成对数据的存取


二、数据库操作

1、创建数据库

create table info_tab(/*primary key 主键 --> 唯一标识符  auto_increment 自动增长*/_id int primary key auto_increment,name varchar(30) not null,/*允许年龄为空(女性年龄不能随意透露*/age int,gender varchar(2) not null
)


2、数据操作(增删改查)

DML(数据库操作语句)

2.1 添加语句

方法1:


insert into info_tab(_id,name,age,gender) values (1,'张三',23,'男')

报错: Error Code: 1366. Incorrect string value: ‘\xE5\xBC\xA0\xE4\xB8\x89’ for column ‘name’ at row 1

解决:
添加以下代码,便可以输入汉字
alter table info_tab convert to character set utf8 ;

注意:
①数据类型要对应

②数据个数要对应

③数据顺序要对应
年龄列插入年龄,姓名列插入姓名

④一定要包含所有非空列
NN:not null 非空列

⑤自动增长列
可以不需要管,默认忽视,会自动配置好
若一定要手动添加:
a.给一个不存在的数据
b.null(会自动增长)


方法2:


默认所有列都要插入数据(一定要按照表的结构中列的顺序来插入)

insert into info_tab values(3,'张四',34,'女')


2.2 删除语句


如果不带条件的话,就会删除该表中所以的内容

delete from info_tab where gender='女'

报错: Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.

原因: MySQL运行在safe-updates模式下,该模式会导致非主键条件下无法执行update或者delete命令

解决: 执行命令SET SQL_SAFE_UPDATES = 0;修改下数据库模式

删除是针对记录而言(不可能删除某个列)


2.3 更新语句


update info_tab set name='汤姆',gender='女' where age=23

若是表中不存在的数据
update info_tab set age=100 where _id=3

结果: 0 row(s) affected Rows matched: 0 Changed: 0 Warnings: 0


2.4 查询语句

查询产生的结果其实是一个虚拟的结果集,并不是把真正的数据取出来传给客户端

select * from 表名 查询某表中所有的记录

select 列名1,列名2 from 表名 ; 查询部分列

select * from 表名 where<查询条件>; 查询部分列


3、手机数据库文件的导入

①在模拟机上

参考资料:如何使用MysqlWorkbench导出一整个sql文件

将以上数据库文件保存为info_tab.sql,然后直接拖入到模拟机中。(在真机上不能这样操作)

在虚拟机sdcard/Download下可以看到info_tab.sql文件

②在真机上

参考资料:如何在Android Studio内打开DDMS


复制SDK路径在文件夹中打开

进入文件夹后 tools->monitor,双击打开

至此,打开了DDMS

报错:

Could not open Selected VM debug port (8700). Make sure you do not have another instance of DDMS or of the eclipse plugin running. If it’s being used by something else, choose a new port number in the preferences.”

解决:

关闭Android studio后,再打开DDMS,无报错

参考资料:查看哪个应用占用了8700端口

疑问:

参考资料: Android Studio 内置模拟器开启 DDMS 后 mnt/sdcard 无法加载目录树

解决:
模拟器版本问题,切换至低版本(非 7.0即可)
开的是 7.0 以上的模拟器,6.0 的还暂时没有做测试,换成5.0 之后问题顺利解决,并且不需要再操作 mnt 下的 sdcard,只需要操作 storage 下的 sdcard 。打印 sd 的绝对路径,出来的也是 storage/sdcard。

疑问:mnt/adcard和storage/sdcard的区别?

切换到模拟机上,可以在storage/sdcard/Download目录下看到我们之前导入的info_tab.sql文件

在sdcard的根目录下导入数据库文件:

导入结果:


三、在Android中对SQLite的使用

1、界面布局

对应于数据库文件info_tab.sql

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><EditTextandroid:id="@+id/name_edt"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:hint="姓名:" /><EditTextandroid:id="@+id/age_edt"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:hint="年龄:"android:numeric="integer" /><!--     android:numeric="integer" 限制输入数据只能是整型--><!--    单选按钮框--><RadioGroupandroid:id="@+id/gender_group"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="5dp"android:text="性别:" /><RadioButtonandroid:id="@+id/male"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:checked="true"android:text="男" /><!--android:checked="true" 设置该按钮为默认选项--><RadioButtonandroid:id="@+id/female"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="15dp"android:text="女" /></RadioGroup><EditTextandroid:id="@+id/id_edt"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:hint="编号" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="8dp"android:orientation="horizontal"><Buttonandroid:id="@+id/insert_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="operate"android:text="添加" /><!--        在xml布局文件中添加点击事件属性--><Buttonandroid:id="@+id/select_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="operate"android:text="查询" /><Buttonandroid:id="@+id/delete_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="operate"android:text="删除" /><Buttonandroid:id="@+id/update_btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1"android:onClick="operate"android:text="修改" /></LinearLayout></LinearLayout>

MainActivity

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}}

效果图:


2、SQLiteOpenHelper类

参考资料:Android之SQLiteOpenHelper

MainActivity

package com.example.sqlitestudy;import androidx.appcompat.app.AppCompatActivity;import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Toast;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}//SQLiteOpenHelperpublic void operate(View view) {switch (view.getId()){case R.id.insert_btn:/*** 添加操作*///参数1:上下文环境// 参数2:数据库名称 (如果只有一个数据库名称,那么这个数据库的位置会是在私有目录中;//                  如果带SD卡路径,那么数据库位置则在指定的路径下)String path= Environment.getExternalStorageDirectory()+"/test.sql";SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,1) {@Overridepublic void onCreate(SQLiteDatabase db) {/*** 创建*/Toast.makeText(MainActivity.this,"数据库创建",Toast.LENGTH_SHORT).show();}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {/*** 升级*/Toast.makeText(MainActivity.this,"数据库升级",Toast.LENGTH_SHORT).show();}};//用于获取数据库对象helper.getReadableDatabase();break;case R.id.select_btn:break;case R.id.delete_btn:break;case R.id.update_btn:break;}}
}

helper.getReadableDatabase(); 用于获取数据库对象

有下列三种可能情况:

1、数据库存在,则直接打开数据库
2、数据库不存在,则调用数据库创建方法,再打开数据库
3、数据库存在,但版本号升高了,则调用数据库升级方法

对应的效果图:

数据库不存在的情况下:

①如果只有一个数据库名称

SQLiteOpenHelper helper=new SQLiteOpenHelper(this,"try8888.sql",null,1) {...
}

那么这个数据库的位置会是在私有目录中:data/data/包名com.example.sqlitestudy

②如果带SD卡路径

String path= Environment.getExternalStorageDirectory()+"/info_tab.sql";
SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,1) {... ...
}

那么数据库位置则在指定的路径下storage/sdcard

版本号升高的情况下:

SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,2){... ...
}


3、SQLiteDatabase类

参考资料:Android之SQLiteDatabase

使用到rawQuery() 、execSQL()

3.1 创建表

SQL语句:
String sql= "create table test_tab(_id integer primary key autoincrement,name varchar(20),age integer,gender varchar)";

执行SQL语句:
db.execSQL(sql);

具体代码:MainActivity

public class MainActivity extends AppCompatActivity {... ...//SQLiteOpenHelperpublic void operate(View view) {switch (view.getId()){case R.id.insert_btn:/*** 添加操作*///参数1:上下文环境 ;参数2:数据库名称 String path= Environment.getExternalStorageDirectory()+"/test.sql";//storage/sdcard/test.sqlLog.d("MainActivity", path);SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,1) {@Override/*** onCreate是一个回调方法,它的执行在数据库不存在,并且已经helper.getReadableDatabase()的情况下* 才会调用onCreate方法,会将返回的SQLiteDatabase对象传回到onCreate中*/public void onCreate(SQLiteDatabase db) {// 创建Toast.makeText(MainActivity.this,"数据库创建",Toast.LENGTH_SHORT).show();/*** 数据库不存在,则会调用onCreate方法,那么我们可以将表的创建工作放在这里完成*///SQL语句String sql= "create table test_tab(_id integer primary key autoincrement,name varchar(20),age integer,gender varchar)";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 升级
Toast.makeText(MainActivity.this,"数据库升级",Toast.LENGTH_SHORT).show();}};SQLiteDatabase db=helper.getReadableDatabase();/*** db.rawQuery() 查询* db.execSQL()  添加、删除、修改、创建表 (execte 执行SQL语句)*/break;... ...}}
}

将生成的test.sql文件导出到桌面上:

导入到MySQLWorkbench中,查看是否生成了test_tab表:

这一步出现了很大的问题,耗费了很多时间,之后发现,虽然SQL语句都是一样的,但是MySQLWorkbench更适合于MySQL。最后下载了DB Browser for SQLite,成功的完成了导入数据库的工作。



3.2 添加数据

传参方式一:

String sql="insert into test_tab (name,age,gender) values ('"+nameStr+"',"+ageStr+",'"+genderStr+"')";
db.execSQL(sql);

方式二:

String sql = "insert into test_tab (name,age,gender) values (?,?,?)";
db.execSQL(sql,new String[]{nameStr,ageStr,genderStr});

具体代码:MainActivity

public class MainActivity extends AppCompatActivity {private EditText nameEdt,ageEdt;private RadioGroup genderGp;private String genderStr="男";//以防什么都不选,设置默认选项为男@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//初始化控件nameEdt=(EditText)findViewById(R.id.name_edt);ageEdt=(EditText)findViewById(R.id.age_edt);//读单选按钮做一个选项切换的事件监听genderGp=(RadioGroup)findViewById(R.id.gender_group);genderGp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {if(checkedId==R.id.male){//男genderStr="男";}else{//女genderStr="女";}}});}//SQLiteOpenHelper//SQLiteDatabasepublic void operate(View view) {switch (view.getId()){case R.id.insert_btn:... ...SQLiteDatabase db=helper.getReadableDatabase();//获取输入框的内容String nameStr=nameEdt.getText().toString();String ageStr=ageEdt.getText().toString();//插入的数据为输入框的内容String sql="insert into test_tab (name,age,gender) values ('"+nameStr+"',"+ageStr+",'"+genderStr+"')";db.execSQL(sql);//提示性语句Toast.makeText(MainActivity.this,"添加成功",Toast.LENGTH_SHORT).show();break;... ...}}
}

效果图:


3.2 查询数据

activity_main.xml

为了让查询到的数据显示在界面上,添加一个ListView控件

  <ListViewandroid:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/stu_list"></ListView>

item.xml

查询结果的子项

<?xml version="1.0" encoding="utf-8"?><!--ListView中子项的布局,包括4个文本-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><TextViewandroid:id="@+id/id_item"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /><TextViewandroid:id="@+id/name_item"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /><TextViewandroid:id="@+id/age_item"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /><TextViewandroid:id="@+id/gender_item"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_weight="1" /></LinearLayout>

MainActivity

因为查询数据也需要用到SQLiteOpenHelper和SQLiteDatabase,为了避免重复代码(同时也是因为SQLiteDatabase对象可以重复执行rawQuery()和execSQL()方法),将new SQLiteOpenHelper和获取SQLiteDatabase对象(db)的相关代码房子onCreate()方法中,并将db提取为全局变量。

参考资料:Android之SimpleCursorAdapter

1、全部查询:

String sql2="select * from test_tab";

查询结果
Cursor c=db.rawQuery(sql2,null);

2、部分查询:

String sql2="select * from test_tab";

查询条件

String idStr=idEdt.getText().toString();
if(!idStr.equals("")){sql2+=" where _id="+idStr;
}

查询结果
Cursor c=db.rawQuery(sql2,null);

具体代码:

public class MainActivity extends AppCompatActivity {private EditText nameEdt,ageEdt,idEdt;private RadioGroup genderGp;private ListView  listView;private String genderStr="男";//以防什么都不选,设置默认选项为男(添加相应的xml设置)private SQLiteDatabase db;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//参数1:上下文环境//参数2:数据库名称 (如果只有一个数据库名称,那么这个数据库的位置会是在私有目录中;//如果带SD卡路径,那么数据库位置则在指定的路径下)String path= Environment.getExternalStorageDirectory()+"/test.sql";//storage/sdcard/test.sqlLog.d("MainActivity", path);SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,1) {@Override/*** onCreate是一个回调方法,它的执行在数据库不存在,并且已经helper.getReadableDatabase()的情况下* 才会调用onCreate方法,会将返回的SQLiteDatabase对象传回到onCreate中*/public void onCreate(SQLiteDatabase db) {// 创建Toast.makeText(MainActivity.this, "数据库创建", Toast.LENGTH_SHORT).show();/*** 数据库不存在,则会调用onCreate方法,那么我们可以将表的创建工作放在这里完成*/String sql = "create table test_tab(_id integer primary key autoincrement,name varchar(20),age integer,gender varchar)";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 升级Toast.makeText(MainActivity.this,"数据库升级",Toast.LENGTH_SHORT).show();}};//用于获取数据库对象//1、数据库存在,则直接打开数据库//2、数据库不存在,则创建数据库,再打开数据库//3、数据库存在,但版本号升高了,则调用数据库升级方法db = helper.getReadableDatabase();... ...idEdt=(EditText)findViewById(R.id.id_edt);... ...//在listView设置显示在界面上的数据(ListView需要Adapter)listView=(ListView)findViewById(R.id.listView);}//SQLiteOpenHelper//SQLiteDatabasepublic void operate(View view) {switch (view.getId()){... ...case R.id.select_btn://select * from 表名 where _id=?String sql2="select * from test_tab";//查询结果Cursor c=db.rawQuery(sql2,null);
//                db.rawQuery(sql,new String[]{})/*** 下面要对查询结果进行处理,将里面的数据显示在界面上*//*SimpleCursorAdapter:参数1 上下文环境;参数2 布局资源;参数3 数据源;*/SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,c,new String[]{"_id","name","age","gender"},new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);listView.setAdapter(adapter);break;... ...}}
}

效果图:

疑问:为甚么要把学号属性名设置为_id?

解答:因为new SimpleCursorAdapter时候识别到数据源Cursor c没有_id ——> SimpleCursorAdapter在定义的初期对这个类的要求就是数据源必须要有_id列 ——> 如果没有,就不能识别,会产生异常 ——> 这就是为什么一开始要把学号属性名设置为_id


3.3 删除数据

public class MainActivity extends AppCompatActivity {public void operate(View view) {... ...//获取输入框的内容String nameStr=nameEdt.getText().toString();String ageStr=ageEdt.getText().toString();//条件查询的条件String idStr = idEdt.getText().toString();... ...switch (view.getId()){... ...case R.id.delete_btn:String sql3="delete from test_tab where _id=?";db.execSQL(sql3,new String[]{idStr});break;... ...}}
}

效果图:


3.4 修改数据

public class MainActivity extends AppCompatActivity {public void operate(View view) {... ...//获取输入框的内容String nameStr=nameEdt.getText().toString();String ageStr=ageEdt.getText().toString();//条件查询的条件String idStr = idEdt.getText().toString();... ...switch (view.getId()){... ...case R.id.update_btn:String sql4="update test_tab set name=?,age=?,gender=? where _id=?";db.execSQL(sql4,new String[]{nameStr,ageStr,genderStr,idStr});break;... ...}}
}

效果图:


3.5 改进

1、在输入框输入信息,操作完一下把输入框清空一下(避免每一次的手动清除)(单选按钮回归到初始设置”男“)

private String genderStr = "男";
malerb = (RadioButton) findViewById(R.id.male);
malerb.setChecked(true);nameEdt.setText("");
ageEdt.setText("");
idEdt.setText("");

2、在操作成功时,提示一下

Toast.makeText(this,"添加成功",Toast.LENGTH_SHORT).show();
Toast.makeText(this,"删除成功",Toast.LENGTH_SHORT).show();
Toast.makeText(this,"修改成功",Toast.LENGTH_SHORT).show();

3.6 完整代码

MainActivity

public class MainActivity extends AppCompatActivity {private EditText nameEdt,ageEdt,idEdt;private RadioGroup genderGp;private ListView  listView;private String genderStr="男";//以防什么都不选,设置默认选项为男(添加相应的xml设置)private SQLiteDatabase db;private RadioButton malerb;//让单选按钮每次操作结束后,能回复到初始状态"男"@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//参数1:上下文环境// 参数2:数据库名称 (如果只有一个数据库名称,那么这个数据库的位置会是在私有目录中;//                  如果带SD卡路径,那么数据库位置则在指定的路径下)String path= Environment.getExternalStorageDirectory()+"/test.sql";//storage/sdcard/test.sqlLog.d("MainActivity", path);SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,1) {@Override/*** onCreate是一个回调方法,它的执行在数据库不存在,并且已经helper.getReadableDatabase()的情况下* 才会调用onCreate方法,会将返回的SQLiteDatabase对象传回到onCreate中*/public void onCreate(SQLiteDatabase db) {// 创建Toast.makeText(MainActivity.this, "数据库创建", Toast.LENGTH_SHORT).show();/*** 数据库不存在,则会调用onCreate方法,那么我们可以将表的创建工作放在这里完成*///SQL语句String sql = "create table test_tab(_id integer primary key autoincrement,name varchar(20),age integer,gender varchar)";db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 升级Toast.makeText(MainActivity.this,"数据库升级",Toast.LENGTH_SHORT).show();}};//用于获取数据库对象//1、数据库存在,则直接打开数据库//2、数据库不存在,则创建数据库,再打开数据库//3、数据库存在,但版本号升高了,则调用数据库升级方法db = helper.getReadableDatabase();//初始化控件nameEdt=(EditText)findViewById(R.id.name_edt);ageEdt=(EditText)findViewById(R.id.age_edt);idEdt=(EditText)findViewById(R.id.id_edt);malerb=(RadioButton)findViewById(R.id.male);//读单选按钮做一个选项切换的事件监听genderGp=(RadioGroup)findViewById(R.id.gender_group);genderGp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {if(checkedId==R.id.male){//男genderStr="男";}else{//女genderStr="女";}}});//在listView设置显示在界面上的数据(ListView需要Adapter)listView=(ListView)findViewById(R.id.listView);}//SQLiteOpenHelper//SQLiteDatabasepublic void operate(View view) {//获取输入框的内容String nameStr=nameEdt.getText().toString();String ageStr=ageEdt.getText().toString();//条件查询的条件String idStr = idEdt.getText().toString();switch (view.getId()){case R.id.insert_btn:/*** db.rawQuery() 查询* db.execSQL()  添加、删除、修改、创建表 (execte 执行SQL语句)*///插入的数据为输入框的内容
//                String sql="insert into test_tab (name,age,gender) values ('"+nameStr+"',"+ageStr+",'"+genderStr+"')";String sql = "insert into test_tab (name,age,gender) values (?,?,?)";db.execSQL(sql,new String[]{nameStr,ageStr,genderStr});Toast.makeText(MainActivity.this,"添加成功",Toast.LENGTH_SHORT).show();break;case R.id.select_btn://select * from 表名 where _id=?String sql2="select * from test_tab";if(!idStr.equals("")){sql2+=" where _id="+ idStr;}//查询结果Cursor c=db.rawQuery(sql2,null);
//                db.rawQuery(sql,new String[]{})/*** 下面要对查询结果进行处理,将里面的数据显示在界面上*//*SimpleCursorAdapter:参数1 上下文环境;参数2 布局资源;参数3 数据源;*/SimpleCursorAdapter adapter=new SimpleCursorAdapter(this,R.layout.item,c,new String[]{"_id","name","age","gender"},new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);listView.setAdapter(adapter);break;case R.id.delete_btn:String sql3="delete from test_tab where _id=?";db.execSQL(sql3,new String[]{idStr});Toast.makeText(this,"删除成功",Toast.LENGTH_SHORT).show();break;case R.id.update_btn:String sql4="update test_tab set name=?,age=?,gender=? where _id=?";db.execSQL(sql4,new String[]{nameStr,ageStr,genderStr,idStr});Toast.makeText(this,"修改成功",Toast.LENGTH_SHORT).show();break;}nameEdt.setText("");ageEdt.setText("");idEdt.setText("");malerb.setChecked(true);}
}

效果图:

如图显示,按下“修改”按钮后,输入框的内容全部清除


四、通过Android的API对SqLite数据库进行操作

参考资料:SQLiteDatabase的4个方法

1、添加insert

case R.id.insert_btn:ContentValues values = new ContentValues();//insert into 表名(列1,列2) values(值1,值2)//values(值1,值2)这一部分交给ContentValues操作values.put("name",nameStr);values.put("age",ageStr);values.put("gender",genderStr);long id = db.insert("test_tab",null,values);Toast.makeText(this,"添加成功,新学员学号是:" + id,Toast.LENGTH_SHORT).show();break;

效果图:


2、查询query

 case R.id.select_btn:Cursor c=db.query("test_tab",null,null,null,null,null,null);//参数3:数据源SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item,c,new String[]{"_id","name","age","gender"},new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item});listView.setAdapter(adapter);break;

效果图:


3、删除delete

case R.id.delete_btn:int count = db.delete("test_tab","_id=?",new String[]{idStr});if(count > 0) {Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();}break;

效果图:

4、修改update

case R.id.update_btn:ContentValues values2 = new ContentValues();//update info_tb set 列1=xx , 列2=xxx where 列名 = 值values2.put("name",nameStr);values2.put("age",ageStr);values2.put("gender",genderStr);int count2 = db.update("test_tb",values2,"_id=?",new String[]{idStr});if(count2 > 0) {Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();}break;

效果图:

5、完整代码

MAinActivity2

//通过Android的API对SqLite数据库进行操作
public class MainActivity2 extends AppCompatActivity {private EditText nameEdt,ageEdt,idEdt;private RadioGroup genderGp;private ListView listView;private String genderStr="男";//以防什么都不选,设置默认选项为男(添加相应的xml设置)private SQLiteDatabase db;private RadioButton malerb;//让单选按钮每次操作结束后,能回复到初始状态"男"@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//参数1:上下文环境// 参数2:数据库名称 (如果只有一个数据库名称,那么这个数据库的位置会是在私有目录中;//                  如果带SD卡路径,那么数据库位置则在指定的路径下)String path= Environment.getExternalStorageDirectory()+"/test.sql";//storage/sdcard/test.sqlLog.d("MainActivity", path);SQLiteOpenHelper helper=new SQLiteOpenHelper(this,path,null,2) {@Override/*** onCreate是一个回调方法,它的执行在数据库不存在,并且已经helper.getReadableDatabase()的情况下* 才会调用onCreate方法,会将返回的SQLiteDatabase对象传回到onCreate中*/public void onCreate(SQLiteDatabase db) {// 创建Toast.makeText(MainActivity2.this, "数据库创建", Toast.LENGTH_SHORT).show();/*** 数据库不存在,则会调用onCreate方法,那么我们可以将表的创建工作放在这里完成*///SQL语句
//                String sql = "create table test_tab(_id integer primary key autoincrement,name varchar(20),age integer,gender varchar)";
//                db.execSQL(sql);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 升级Toast.makeText(MainActivity2.this,"数据库升级",Toast.LENGTH_SHORT).show();}};//用于获取数据库对象//1、数据库存在,则直接打开数据库//2、数据库不存在,则创建数据库,再打开数据库//3、数据库存在,但版本号升高了,则调用数据库升级方法db = helper.getReadableDatabase();//初始化控件nameEdt=(EditText)findViewById(R.id.name_edt);ageEdt=(EditText)findViewById(R.id.age_edt);idEdt=(EditText)findViewById(R.id.id_edt);malerb=(RadioButton)findViewById(R.id.male);//读单选按钮做一个选项切换的事件监听genderGp=(RadioGroup)findViewById(R.id.gender_group);genderGp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {if(checkedId==R.id.male){//男genderStr="男";}else{//女genderStr="女";}}});//在listView设置显示在界面上的数据(ListView需要Adapter)listView=(ListView)findViewById(R.id.listView);}//SQLiteOpenHelper//SQLiteDatabasepublic void operate(View view) {//获取输入框的内容String nameStr=nameEdt.getText().toString();String ageStr=ageEdt.getText().toString();//条件查询的条件String idStr = idEdt.getText().toString();switch (view.getId()){case R.id.insert_btn:/**在SqliteDatabase类下,提供四个方法* insert(添加)、delete(删除)、update(修改)、query(查询)* 都不需要写sql语句* 参数1:你所要操作的数据库表的名称* 参数2:可以为空的列  如果第三个参数是null或者说里面没有数据* 那么我们的sql语句就会变为insert into info_tb () values ()  ,在语法上就是错误的* 此时通过参数3指定一个可以为空的列,语句就变成了insert into info_tb (可空列) values (null)*/ContentValues values = new ContentValues();//insert into 表名(列1,列2) values(值1,值2)//values(值1,值2)这一部分交给ContentValues操作values.put("name",nameStr);values.put("age",ageStr);values.put("gender",genderStr);long id = db.insert("test_tab",null,values);Toast.makeText(this,"添加成功,新学员学号是:" + id,Toast.LENGTH_SHORT).show();break;case R.id.select_btn:/*** 参数1:表名* 参数2:你所要查询的列 {"name","age","gender"} 如果想要查询所有的话,传入null或{*}* 参数3:条件(针对列)* 参数5:分组* 参数6:当 group by对数据进行分组后,可以通过having来去除不符合条件的组* 参数7:排序*/Cursor c=db.query("test_tab",null,null,null,null,null,null);//参数3:数据源SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item,c,new String[]{"_id","name","age","gender"},new int[]{R.id.id_item,R.id.name_item,R.id.age_item,R.id.gender_item});listView.setAdapter(adapter);break;case R.id.delete_btn:int count = db.delete("test_tab","_id=?",new String[]{idStr});if(count > 0) {Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();}break;case R.id.update_btn:ContentValues values2 = new ContentValues();//update info_tb set 列1=xx , 列2=xxx where 列名 = 值values2.put("name",nameStr);values2.put("age",ageStr);values2.put("gender",genderStr);int count2 = db.update("test_tab",values2,"_id=?",new String[]{idStr});if(count2 > 0) {Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show();}break;}nameEdt.setText("");ageEdt.setText("");idEdt.setText("");malerb.setChecked(true);}
}

五、SQLite总结

SQLite数据库是一个轻量级的数据库,本质上是一个二进制文件。


六、数据库操作的封装

Student

public class Student{//私有属性private int id;private String name;private int age;private String gender;//无参构造public Student(){}//有参构造(3个参数)public Student(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}//有参构造(4个参数)public Student(int id, String name, int age, String gender) {super();this.id = id;this.name = name;this.age = age;this.gender = gender;}//创建的setter和getter方法public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}
}

StudentDao

//Dao(data access object)数据访问对象
public class StudentDao {//之后的数据库操作都需要用到SQLiteDatabaseprivate SQLiteDatabase db;//先实例化StudentDao这个类,然后实例化出来的对象再点db的方法,所以,在这个类的实例化过程中,将db对象获取到public StudentDao(final Context context){String path= Environment.getExternalStorageDirectory()+"/test.sql";SQLiteOpenHelper helper=new SQLiteOpenHelper(context,path,null,2) {@Overridepublic void onCreate(SQLiteDatabase db) {// 创建}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {// 升级}};//获取对象db=helper.getReadableDatabase();}/*** 添加操作*/public void addStudent(){}/*** 查询操作*/public void getStudent(){}/*** 删除操作*/public void deleteStudent(){}/*** 修改操作*/public void uodatae(){}
}

MainActivity3

public class MainActivity3 extends AppCompatActivity {private EditText nameEdt, ageEdt, idEdt;private RadioGroup genderGp;private ListView listView;private String genderStr = "男";//以防什么都不选,设置默认选项为男(添加相应的xml设置)private RadioButton malerb;//让单选按钮每次操作结束后,能回复到初始状态"男"private StudentDao dao;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//实例化dao = new StudentDao(this);//初始化控件nameEdt = (EditText) findViewById(R.id.name_edt);ageEdt = (EditText) findViewById(R.id.age_edt);idEdt = (EditText) findViewById(R.id.id_edt);malerb = (RadioButton) findViewById(R.id.male);//读单选按钮做一个选项切换的事件监听genderGp = (RadioGroup) findViewById(R.id.gender_group);genderGp.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {if (checkedId == R.id.male) {//男genderStr = "男";} else {//女genderStr = "女";}}});listView=(ListView)findViewById(R.id.listView);}public void updataeStudent(View view) {//获取输入框的内容String nameStr = nameEdt.getText().toString();String ageStr = ageEdt.getText().toString();//条件查询的条件String idStr = idEdt.getText().toString();switch (view.getId()) {case R.id.insert_btn:Student stu = new Student(nameStr, Integer.parseInt(ageStr), genderStr);dao.addStudent(stu);Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();break;case R.id.select_btn:break;case R.id.delete_btn:break;case R.id.update_btn:break;}nameEdt.setText("");ageEdt.setText("");idEdt.setText("");malerb.setChecked(true);}
}

1、添加操作

StudentDao

public void addStudent(Student stu){String sql="insert into test_tab (name,age,gender) values (?,?,?)";db.execSQL(sql,new String[]{stu.getName(),stu.getAge()+"",stu.getGender()});}

MainActivity3

case R.id.insert_btn:Student stu = new Student(nameStr, Integer.parseInt(ageStr), genderStr);dao.addStudent(stu);Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();break;

效果图:


2、查询操作

StudentDao

public Cursor getStudent(String...strings){//1、查询所有(没有参数)String sql="select * from test_tab";//2、含条件查询(姓名、年龄、编号)(参数形式:第一个参数指明条件,第二个参数指明条件值)if(strings.length!=0){sql+=" where "+strings[0]+"='"+strings[2]+"'";//在查询时,age用''修饰是没关系的}Cursor c=db.rawQuery(sql,null);return c;}

MainActivity3

case R.id.select_btn:String key = "", value = "";//需要判断nameEdt ageEdt idEdt哪个不为空,不为空的就是getStudent()需要传入的参数if (!nameStr.equals("")) {key = "name";value = nameStr;} else if (!ageStr.equals("")) {key = "age";value = ageStr;} else if (!idStr.equals("")) {key = "_id";value = idStr;}Cursor c;if (key.equals("")) {c = dao.getStudent();} else {c = dao.getStudent(key, value);}SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, c,new String[]{"_id", "name", "age", "gender"},new int[]{R.id.id_item, R.id.name_item, R.id.age_item, R.id.gender_item});listView.setAdapter(adapter);break;

效果图:


3、删除操作

StudentDao

public void deleteStudent(String...strings){String sql="delete from test_tab where "+strings[0]+"='"+strings[1]+"'";db.execSQL(sql);}

MainActivity3

因为delete中也需要”判断输入框的内容是否为空“的操作,所以将这部分提取为一个getParams()方法

case R.id.delete_btn:String[] params = getParams(nameStr, ageStr, idStr);dao.deleteStudent(params[0],params[1]);Toast.makeText(this, "删除成功", Toast.LENGTH_SHORT).show();break;
public String[] getParams(String nameStr, String ageStr, String idStr) {String[] params = new String[2];if (!nameStr.equals("")) {params[0] = "name";params[1] = nameStr;} else if (!ageStr.equals("")) {params[0] = "age";params[1] = ageStr;} else if (!idStr.equals("")) {params[0] = "_id";params[1] = idStr;}return params;
}

效果图:


4、修改操作

StudentDao

public void updateStudent(Student stu){String sql = "update test_tab set name=?,age=?,gender=? where _id=?";db.execSQL(sql,new Object[]{stu.getName(),stu.getAge(),stu.getGender(),stu.getId()});
}

MainActivity3

case R.id.update_btn:Student stu2=new Student(Integer.parseInt(idStr),nameStr,Integer.parseInt(ageStr),genderStr);dao.updateStudent(stu2);Toast.makeText(this,"修改成功",Toast.LENGTH_SHORT).show();break;

效果图:


5、小结

StudentDao

另一种查询方法

moveToNext() 可以将cursor移动到下一条记录上

public ArrayList<Student> getStudentInList(String...strings){ArrayList<Student> list=new ArrayList<>();Cursor c=getStudent(strings);while (c.moveToNext()){int id=c.getInt(0);String name=c.getString(1);int age=c.getInt(2);String gender=c.getString(3);Student s=new Student(id,name,age,gender);list.add(s);}return list;
}

Android之本地数据存储(SQLite数据库)相关推荐

  1. android模拟器的数据存放,Android模拟器在哪里存储SQLite数据库?

    Android模拟器在哪里存储SQLite数据库? 我正在开发一个将数据存储在SQLite数据库中的Android应用程序. 我的问题是,当您使用模拟器时,此数据库文件存储在文件系统中的哪个位置? 我 ...

  2. Android App开发基础篇—数据存储(SQLite数据库)

    Android App开发基础篇-数据存储(SQLite数据库) 前言:Android中提供了对SQLite数据库的支持.开发人员可以在应用中创建和操作自己的数据库来存储数据,并对数据进行操作. 一. ...

  3. Android之本地数据存储(一):SharedPreferences

    所有的应用程序都必然涉及数据的输入与输出.在Android系统中,主要有五种数据存储模式: 1 . Sharedferences:Sharedferences是一种轻型的数据存储方式,本质上是基于XM ...

  4. Android数据存储——SQLite数据库(模板)

    本篇整合Android使用数据库,要保存一个实体类的样本. 首先看一下数据库语句: ORM:关系对象映射 添加数据: ContentValues values = new ContentValues( ...

  5. [Android Studio]Android 数据存储--SQLite数据库存储

  6. android 储存方案,Android本地数据存储方案(一)

    Android系列的博客主要是记录和总结自己在平时学习之中遇到的问题,方便日后用到时查看,同时也希望对读者有所帮助.不足之处,欢迎指正~ 在说到Android数据存储之前,先提一下数据持久化,所谓数据 ...

  7. Android本地数据存储: Reservoir

    一:前言 今天做项目,准备使用本地存储,把一些数据存在本地磁盘上,比如用户名.密码这样的.其实大家都知道,这种情况最常用的就是SharedPreferences了,我也不例外,脑子里第一个想到的就是用 ...

  8. [免费专栏] Android安全之数据存储与数据安全「详解」

    也许每个人出生的时候都以为这世界都是为他一个人而存在的,当他发现自己错的时候,他便开始长大 少走了弯路,也就错过了风景,无论如何,感谢经历 Android安全付费专栏长期更新,本篇最新内容请前往: [ ...

  9. 在 Android 应用程序中使用 SQLite 数据库以及怎么用

    part one : android SQLite 简单介绍 SQLite 介绍 SQLite 一个非常流行的嵌入式数据库.它支持 SQL 语言,而且仅仅利用非常少的内存就有非常好的性能.此外它还是开 ...

  10. Android基础_数据存储

    2019独角兽企业重金招聘Python工程师标准>>> Android基础_数据存储 Android数据存储的几种形式 继承SQLiteOpenHelper public class ...

最新文章

  1. linux编译安装jpeg,Linux下JPEG库安装脚本(转)
  2. 在开发流程中嵌入安全测试
  3. OSChina 周二乱弹 ——clouddyy快来! 这个姑娘好萌你要不?
  4. 代码补全_AI加持,Kite增加智能代码补全功能:减少一半操作,实时补全
  5. pythonmessage用法_请问Mac下如何用python读取iMessage信息?
  6. 江苏小高考计算机操作题软件,江苏小高考现神题:求微信启动画面的拍摄时间...
  7. Leetcode 刷题笔记(十七) —— 二叉树篇之公共祖先问题
  8. DB2分区表删除和添加分区
  9. 代理服务器的工作原理
  10. Mac小白应该使用App Tamer减慢或停止哪些应用程序?
  11. 百度网盘电脑端看视频声音巨小的解决办法(windows10)
  12. 思科网络设备常用命令
  13. 科研写作——常见句式(一)
  14. 爬虫练习-荔枝直播(分享页)
  15. IT30: IT人为什么那么有毅力
  16. Ten Googol
  17. mcrypt cbc php7,PHP7.1中使用openssl替换mcrypt的实例详解
  18. 新中国建国以来汇率的变化追踪
  19. 离职后为讨薪删公司数据,结果被判 11 个月...
  20. 阿里云网站ICP备案一定要知道的东西

热门文章

  1. Java 的三种 Base64
  2. 换服务器系统怎么迁移,更换服务器时,数据迁移的方法
  3. 公众号写作排版指南教程v1.0
  4. smartSVN用法
  5. matlab 量化与过采样,[转载]降采样,过采样,欠采样,子采样,下采样
  6. 软工视频-----系统结构图
  7. Jquery头像编辑器
  8. 字节码编程 | 使用Javassist生成JavaBean
  9. 一个基于QT的开源串口调试工具
  10. 【转】Latex入门教程