`
TonySun3544
  • 浏览: 161495 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于SQLite数据库的那些事儿

阅读更多

 

一、基础知识

在Android平台上,集成了一个嵌入式关系型数据库——SQLite。SQLite第一个Alpha版本诞生于2000年5月。它是遵守ACID的关联式数据库管理系统,包含在一个相对小的C库中,同时是D.RichardHipp建立的公有领域项目。SQLite官方网站: http://www.sqlite.org/;SQLite中文社区:http://www.sqlite.com.cn/。

SQLite3支持NULL、INTEGER、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上SQLite3也接受varchar(n)、char(n)、decimal(p,s)等数据类型,只不过在运算或保存时会转成对应的五种数据类型。 SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。例如:可以在INTEGER类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值。但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数,当向这种字段保存除整数以外的数据时,将会产生错误。 另外,SQLite在解析CREATE TABLE语句时,会忽略CREATE TABLE语句中跟在字段名后面的数据类型信息,如下面语句中会忽略name字段的类型信息:

CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))即使指定了字段的数据长度,该字段仍然可以保存超过指定长度的内容。

SQLite可以解析大部分标准SQL语句,如:

查询语句:select * from 表名 where 条件子句 group by 分组字句 having ... order by 排序子句

如:select * from person

    select * from person order by id desc

    select name from person group by name having count(*)>1

分页SQL与MySQL类似,下面SQL语句获取5条记录,跳过前面3条记录

select * from person limit 5 offset 3 或者 select * from person limit 3,5

插入语句:insert into 表名(字段列表) values(值列表)。如: insert into person(name, age) values('孙小圣',3)

更新语句:update 表名 set 字段名=值 where 条件子句。如:update person set name=' 孙小圣' where id=10

删除语句:delete from 表名 where 条件子句。如:delete from person where id=10

 

 

二、操作数据库

在Android系统里为我们提供了一个名为SQLiteOpenHelper的抽象类,必须继承它才能使用,它是通过对数据库版本进行管理。为了实现对数据库版本进行管理,SQLiteOpenHelper类提供了两个重要的方法,分别是onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用,在onCreate()方法里可以生成数据库表结构及添加一些应用使用到的初始化数据。onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号,而数据库的版本是由程序员控制的,假设数据库现在的版本是1,由于业务的变更,修改了数据库表结构,这时候就需要升级软件,升级软件时希望更新用户手机里的数据库表结构,为了实现这一目的,可以把原来的数据库版本设置为2(有同学问设置为3行不行?当然可以,如果你愿意,设置为100也行),并且在onUpgrade()方法里面实现表结构的更新。当软件的版本升级次数比较多,这时在onUpgrade()方法里面可以根据原版号和目标版本号进行判断,然后作出相应的表结构及数据更新。

 

SQLiteOpenHelper类的getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase()方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。

 

①:编写实现SQLiteOpenHelper类的子类DBOpenHelper

必须显式调用父类的构造方法:super(context, DATABASE_NAME, null, DATABASE_VERSION);

参数2是数据库名称,例如"sxs",可以没有后缀名,也可以有,例如" sxs.db"。

参数3是游标工厂,可以设为null使用默认的游标工厂。

参数4是版本号,例如是"1"。

数据库的位置:/data/data/<package_name>/databases/ sxs.db

 

②:创建数据库表

在onCreate(SQLiteDatabase db)方法中添加如下代码:

db.execSQL("create table person(personid integer primary key autoincrement, name varchar(20))");

 

SQLiteDatabase sQLiteDatabase = DBOpenHelper.getWritableDatabase();//第一次调用该方法就会创建数据库

第一次调用getWritableDatabase()或getReadableDatabase()方法后,SQLiteOpenHelper会缓存当前的SQLiteDatabase实例,SQLiteDatabase实例正常情况下会维持数据库的打开状态,所以你不再需要SQLiteDatabase实例时,请及时调用close()方法释放资源。一旦SQLiteDatabase实例被缓存,多次调用getWritableDatabase()或getReadableDatabase()方法得到的都是同一实例。

 

③:通过SQLiteDatabase进行增删改查。CRUD是指增加(Create)、查询(Retrieve)(重新得到数据)、更新(Update)和删除(Delete)几个单词的首字母简写。

第一种方式:SQLiteDatabase.execSQL("   ")、rawQuery("   ");

execSQL()方法可以执行insert、delete、update和CREATE TABLE之类有更改行为的SQL语句;rawQuery()方法用于执行select语句。rawQuery()方法的第一个参数为select语句,第二个参数为select语句中占位符参数的值,如果select语句没有使用占位符,第二个参数设置为null。rawQuery()方法返回Cursor对象,Cursor是结果集游标,用于对结果集进行随机访问,Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true )和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true )。

 

第二种方式:SQLiteDatabase.insert("   ")、delete("   ")、update("   ")和query("   ");

各个字段的数据使用ContentValues进行存放。ContentValues类似于MAP,它提供了存取数据对应的put(String key, Xxx value)和getAsXxx(String key)方法, key为字段名称,value为字段值,Xxx指的是各种常用的数据类型,如:String、Integer等。

 

 

三、关于SQLite数据库中的事务操作

使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction()方法时会检查事务的标志是否为成功,如果程序执行到endTransaction()之前调用了setTransactionSuccessful()方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful()方法则回滚事务。使用例子如下:

 

 

SQLiteDatabase db = ....;
db.beginTransaction();//开始事务
try {
    db.execSQL("insert into person(name, age) values(?,?)", new Object[]{"张三", 5});
    db.execSQL("update person set name=? where personid=?", new Object[]{"李四", 1});
    db.setTransactionSuccessful();//调用此方法会在执行到endTransaction()时提交当前事务,如果不调用此方法则回滚事务。
} finally {
    db.endTransaction();//结束事务。由事务的标志决定是提交事务,还是回滚事务
} 
db.close(); 

 上面两条SQL语句在同一个事务中执行。

 

 

 

四、列表显示数据

ListView由多个Item组成,Item可以自定义。每个Item由ImageView(图片)和TextView(文本)组成。

首先定义Item显示界面。

item.xml:

 

	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:orientation="horizontal"
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content"
	    >
		<TextView  
		    android:layout_width="80dip" 
		    android:layout_height="wrap_content" 
		    //android:text="1"
		    android:id="@+id/id"
		    />
		<TextView  
		    android:layout_width="100dip" 
		    android:layout_height="wrap_content" 
		    //android:text="lisi"
		    android:id="@+id/name"
		    />
		<TextView  
		    android:layout_width="fill_parent" 
		    android:layout_height="wrap_content" 
		    //android:text="22"
		    android:id="@+id/age"
		    />
	</LinearLayout>
 

 

其次定义主界面。

main.xml

 

	<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:orientation="vertical"
	    android:layout_width="fill_parent"
	    android:layout_height="fill_parent"
	    >
	    <Button  
		    android:layout_width="fill_parent" 
		    android:layout_height="wrap_content" 
		    android:text="添加数据"
		    android:id="@+id/insertbutton"
		    />
	    <LinearLayout
		    android:orientation="horizontal"
		    android:layout_width="fill_parent"
		    android:layout_height="wrap_content"
		    >
		    <TextView  
			    android:layout_width="80dip" 
			    android:layout_height="wrap_content" 
			    android:text="ID"
			    />
			<TextView  
			    android:layout_width="100dip" 
			    android:layout_height="wrap_content" 
			    android:text="姓名"
			    />
			<TextView  
			    android:layout_width="fill_parent" 
			    android:layout_height="wrap_content" 
			    android:text="年龄"
			    />
		</LinearLayout>
		<ListView  
		    android:layout_width="fill_parent" 
		    android:layout_height="fill_parent" 
		    android:id="@+id/listView"
		    />
	</LinearLayout>
 

 

然后把数据绑定到ListView中,并为Item指定界面。

 

	//可以使用SimpleAdapter
        List<Person> persons = personService.selectByPage(0, 5);
	//创建Map对象
        List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
        for(Person person : persons){
        	Map<String, Object> item = new HashMap<String, Object>();
        	item.put("id", person.getId());
        	item.put("name", person.getName());
        	item.put("age", person.getAge());
        	data.add(item);
        }        
        ListView listView = (ListView) this.findViewById(R.id.listView);
        SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item, 
        		new String[]{"id", "name", "age"}, new int[]{R.id.id, R.id.name, R.id.age});        
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new OnItemClickListener(){
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			//parent:当前点击的ListView对象				
			//view:当前点击的条目所绑定的view
			//position:绑定数据的位置
			//id:view在ListView中的id
			ListView aListView = (ListView) parent;
			Map<String, Object> item = (Map<String, Object>) aListView.getItemAtPosition(position);
			Toast.makeText(MainActivity.this, item.get("id").toString(), 1).show();
		}        	
        });


	//也可以使用SimpleCursorAdapter
        /*ListView listView = (ListView) this.findViewById(R.id.listView);
        Cursor cursor = personService.selectCursorByPage(0, 5);
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor,
        		new String[]{"_id", "name", "age"}, new int[]{R.id.id, R.id.name, R.id.age}); 
        listView.setAdapter(adapter);

        listView.setOnItemClickListener(new OnItemClickListener(){
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			//parent:当前点击的ListView对象				
			//view:当前点击的条目所绑定的view
			//position:绑定数据的位置
			//id:view在ListView中的id
			ListView aListView = (ListView) parent;
			Cursor item = (Cursor) aListView.getItemAtPosition(position);
			int personid = item.getInt(item.getColumnIndex("_id"));
			Toast.makeText(MainActivity.this, personid + "", 1).show();
		}        	
        });*/
 

 

当使用SimpleCursorAdapter时,可能会出现以下异常信息:

SimpleCursorAdapter:ERROR/AndroidRuntime(344): Caused by: java.lang.IllegalArgumentException: column '_id' does not exist。

如何解决上述异常?

方法1:创建表时直接定义表的主键列名为"_id"。

方法2:在查询时为表的主键指定别名为"_id"。

 

1
0
分享到:
评论

相关推荐

    使用C#开发的Sqlite数据库创建、操作的源码项目工程

    这是一个使用C#开发的Sqlite数据库创建、操作的源码工程,关于Sqlite的所有操作已经单独创建了专门的跨平台【.NETCore3.1】类库包含相应的帮助类,可以直接生成后拿到任何项目中直接使用,高效简单,省去了从头开发...

    Android实验报告Sqlite数据库操作.pdf

    Android SQLite 数据库操作报告 一、实验目的 Android 实验报告的主要目的是熟悉 Android 平台的文件操作、掌握 Android SQLite 数据库的设计和应用、熟悉 XML 和 JSON 文件的读取。通过本实验,用户可以掌握 ...

    SQLite数据库 加密解密工具

    SQLite数据库是一种轻量级、自包含的SQL数据库引擎,常被用在嵌入式系统和移动应用中。在处理敏感数据时,为了保护信息安全,对SQLite数据库进行加密是必要的步骤。本文将详细介绍如何使用.NET环境下的SQLite加密...

    Delphi版SQLite数据库工具

    这款Delphi工具则提供了更加便捷的方式来操作SQLite数据库,尤其对于那些使用Delphi进行开发的项目。 首先,该工具的一大亮点是支持查询加密的SQLite数据库。这意味着用户可以对存储的数据进行安全保护,防止未经...

    SQLiteCompareSetup(SQLite数据库比较工具)

    SQlite数据库工具 供比较两个SQLite数据库所用。

    SQLite数据库逆向分析1

    SQLite数据库逆向分析 SQLite数据库逆向分析是一门复杂的技术领域,涉及到软件逆向分析、数据库逆向分析、反汇编、反编译等技术领域。以下为本节课的知识点总结: 1. SQLite数据库逆向分析简介 SQLite数据库逆向...

    SQLite数据库打开工具

    SQLite是一款轻量级的、开源的、自包含的SQL数据库引擎,它不需要单独的服务器进程,可以直接嵌入到各类应用程序中。SQLite具有高度移植性,支持多种操作系统和编程语言,如Windows、Linux、Mac OS、Java、C++、...

    js 访问 sqlite数据库

    SQLite则是一个轻量级的、自包含的、无服务器的、事务性的SQL数据库引擎,它被广泛集成到各种应用程序中,包括Web应用。本文将深入探讨如何使用JavaScript访问SQLite数据库,以及相关的关键知识点。 首先,...

    Sqlite 数据库删除恢复

    SQLite数据库在移动设备和嵌入式系统中广泛应用,如iPhone和Android平台,因为它的轻量级和无需服务器的特性。然而,数据丢失是常见的问题,可能是由于意外删除、软件故障或者用户错误。在这种情况下,"SQLite数据库...

    VB6.0 操作SQLite 数据库的完整示例代码

    在VB6.0中操作SQLite数据库,是一种将轻量级、高性能的SQLite数据库与传统的Visual Basic编程环境相结合的方法。SQLite是一种自包含、无服务器、零配置、事务性的SQL数据库引擎,广泛应用于移动设备、嵌入式系统以及...

    全国省市区sqlite数据库

    全国省市区sqlite数据库是一种高效、轻量级的方式来存储和管理中国的行政区域划分数据。SQLite是一个开源的嵌入式关系数据库,它不需要单独的服务器进程,可以直接在应用程序中使用,非常适合处理小到中型规模的数据...

    sqlite 数据库加解密工具 绿色版v2

    SQLite 是一个轻量级的、开源的数据库管理系统,它无需单独的服务器进程,可以直接嵌入到应用程序中。这个“SQLite 数据库加解密工具 绿色版v2”显然是专门针对 SQLite 数据库进行加密和解密操作的一款软件。在本文...

    SQLite数据库文件自收缩_sqlite3_

    在提供的压缩包文件“SQLite数据库文件自收缩.pdf”中,可能包含了关于如何使用VACUUM和PRAGMA语句进行数据库文件收缩的详细步骤、注意事项以及最佳实践。通过阅读这份文档,你可以深入理解这两个方法的工作原理,并...

    Android中SQLite数据库查看工具

    SQLite是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,您不需要在系统中配置。 就像其他数据库,SQLite 引擎不是一个...

    C++操作sqlite数据库

    C++操作sqlite数据库简明教程及示例代码 C++操作sqlite数据库是指使用C++语言来操作sqlite数据库的过程。sqlite数据库是轻量级的关系数据库管理系统,广泛应用于移动设备、嵌入式系统和桌面应用程序中。使用C++语言...

    基于QT+sqlite数据库实现员工信息管理系统源码+项目说明.zip

    基于QT+sqlite数据库实现员工信息管理系统源码+项目说明.zip基于QT+sqlite数据库实现员工信息管理系统源码+项目说明.zip基于QT+sqlite数据库实现员工信息管理系统源码+项目说明.zip基于QT+sqlite数据库实现员工信息...

    VB 6.0操作Sqlite数据库(查询、添加、更新、删除)

    SQLite是一个轻量级的、自包含的数据库引擎,适用于各种应用程序,特别是那些需要在没有服务器的情况下运行的场景。以下是对这些知识点的详细说明: **连接SQLite数据库** 首先,你需要一个SQLite的ADO驱动,例如...

    SQLite数据库查看工具(SQLiteBrowser)

    SQLite数据库是一种轻量级、开源的嵌入式关系数据库,广泛应用于移动应用、小型桌面应用以及需要快速存储和检索数据的任何系统。SQLiteBrowser是一款免费且开源的图形用户界面工具,用于浏览、编辑和管理SQLite...

    Sqlite数据库加密、修改密码工具

    Sqlite数据库加密、解密工具,主要是用于进行给Sqlite数据库进行加密,修改密码的工具

    SQLITE数据库查询时中文乱码

    在使用SQLite数据库进行查询操作时,遇到中文乱码问题,通常是由于编码设置不正确或数据存储与读取过程中编码不一致导致的。SQLite本身支持多种字符编码,包括UTF-8、UTF-16等,但在实际应用中,如果没有正确配置,...

Global site tag (gtag.js) - Google Analytics