android sqlite3最全使用大全

Android的默认数据库引擎是精简版。SQLite是一个轻量级的事务数据库引擎,磁盘存储空间和内存占用都很少,因此在Android,IOS等手机操作系统上创建数据库,它是一个完美的选择。

 

在处理SQLite时需要考虑的事情:

1.数据类型完整性的维护不能依赖SQLite,你可以把某一数据类型的值放在另外一种数据类型的列中(例如把字符串存在整数列)。

2.引用完整性不能依赖SQLite,没有外键(FOREIGN KEY)和JOIN语句。

3.SQLite默认安装不支持完整的Unicode,需要选装。

 

在本教程中,我们将创建一个简单的应用程序商店的员工数据库:

 

1.Employees 员工表

2.Dept 部门表

 

视图

ViewEmps:显示员工和他们的相关部门。

创建SQLite数据库

 

默认情况下,Android中的SQLite没有管理界面或应用程序去创建和管理数据库,所以我们要用代码来创建数据库。

 

首先,我们将创建一个类来处理所需的所有操作,如创建数据库,创建表,插入和删除记录等数据库处理。

 

第一步是创建一个类,继承SQLiteOpenHelper类。这个类提供了覆盖处理与数据库的两种方法:

 

1. OnCreate中(SQLiteDatabase db) :创建数据库时调用,在这里我们可以创建表和列,创建视图或触发器。

 

2.onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):

当我们作出修改,如修改,删除,创建新的表的数据库调用。

 

我们的类有如下成员:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

public class DatabaseHelper extends SQLiteOpenHelper {

 

static final String dbName="demoDB";

static final String employeeTable="Employees";

static final String colID="EmployeeID";

static final String colName="EmployeeName";

static final String colAge="Age";

static final String colDept="Dept";

 

static final String deptTable="Dept";

static final String colDeptID="DeptID";

static final String colDeptName="DeptName";

 

static final String viewEmps="ViewEmps";

构造函数

 

1

2

3

public DatabaseHelper(Context context) {

  super(context, dbName, null,33);

  }

super类的构造函数有如下参数:

Context son: 连接到数据库的上下文

dbName:数据库的名称

CursorFactory:有时候,我们可能会使用Cursor类的扩展类来进行一些额外的验证或操作,实现对数据库运行查询。在这种情况下,我们传递CursorFactory的实例,返回要使用的默认游标,而不是返回到我们的派生类的引用。在这个例子中,我们将使用标准的游标接口,因此,我们将CursorFactory参数设置为null。

Version:数据库架构的版本。构造函数创建一个新的空白数据库时需要指定名称和版本。

创建数据库

第一个覆盖父类的方法是onCreate(SQLiteDatabase db):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

public void onCreate(SQLiteDatabase db) {

  // TODO Auto-generated method stub

   

  db.execSQL("CREATE TABLE "+deptTable+" ("+colDeptID+ " INTEGER PRIMARY KEY , "+

    colDeptName+ " TEXT)");

   

  db.execSQL("CREATE TABLE "+employeeTable+"

    ("+colID+" INTEGER PRIMARY KEY AUTOINCREMENT, "+

        colName+" TEXT, "+colAge+" Integer, "+colDept+"

    INTEGER NOT NULL ,FOREIGN KEY ("+colDept+") REFERENCES

    "+deptTable+" ("+colDeptID+"));");

   

   

  db.execSQL("CREATE TRIGGER fk_empdept_deptid " +

    " BEFORE INSERT "+

    " ON "+employeeTable+

     

    " FOR EACH ROW BEGIN"+

    " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+deptTable+"

    WHERE "+colDeptID+"=new."+colDept+" ) IS NULL)"+

    " THEN RAISE (ABORT,'Foreign Key Violation') END;"+

    "  END;");

   

  db.execSQL("CREATE VIEW "+viewEmps+

    " AS SELECT "+employeeTable+"."+colID+" AS _id,"+

    " "+employeeTable+"."+colName+","+

    " "+employeeTable+"."+colAge+","+

    " "+deptTable+"."+colDeptName+""+

    " FROM "+employeeTable+" JOIN "+deptTable+

    " ON "+employeeTable+"."+colDept+" ="+deptTable+"."+colDeptID

    );

  //Inserts pre-defined departments

  InsertDepts(db); 

 }

 

该函数创建含列的表,视图和触发器。该函数在数据库创建时被调用。当数据库在磁盘上不存在时该方法被

 

调用,它在应用程序首次运行时执行,同一设备只执行一次。

 

升级数据库

 

有时候,我们需要通过改变架构来升级数据库,然后添加新的表或改变列的数据类型。这些在onUpgrade

 

(SQLiteDatabase db,int old Version,int newVerison)函数中完成。

 

1

2

3

4

5

6

7

8

9

10

11

12

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

  // TODO Auto-generated method stub

   

  db.execSQL("DROP TABLE IF EXISTS "+employeeTable);

  db.execSQL("DROP TABLE IF EXISTS "+deptTable);

   

  db.execSQL("DROP TRIGGER IF EXISTS dept_id_trigger");

  db.execSQL("DROP TRIGGER IF EXISTS dept_id_trigger22");

  db.execSQL("DROP TRIGGER IF EXISTS fk_empdept_deptid");

  db.execSQL("DROP VIEW IF EXISTS "+viewEmps);

  onCreate(db);

 }

该函数在构造函数中的版本号参数有所改变时被调用。

当我们想添加一些修改到我们的数据库中,我们必须更改构造函数中的版本号的数字。

因此我们可以将版本号2传递给构造函数用于代替版本1:

1

2

3

4

5

public DatabaseHelper(Context context) {

  super(context, dbName, null,2);

   

  // TODO Auto-generated constructor stub

 }

原来:super(context, dbName, null,1);

应用程序会理解为你想升级数据库,onUpgrade函数被调用。该方法的一个典型应用是删除表,然后创建表

做相应修改。

管理外键约束

我们提到过,在此之前,由默认的SQLite 3不支持外键约束,但是我们可以强制使用触发器这样的约束:我们将创建一个触发器,确保插入一个新雇员时,他/她的部门值在原部门表中已经存在。创建一个触发器的SQL语句:

1

2

3

4

5

CREATE TRIGGER fk_empdept_deptid Before INSERT ON Employees

FOR EACH ROW BEGIN

    SELECT CASE WHEN ((SELECT DeptID FROM Dept WHERE DeptID =new.Dept ) IS NULL)

    THEN RAISE (ABORT,'Foreign Key Violation') END;

    END

在onCreate方法中,我们创建这样的触发器:

1

2

3

4

5

6

7

8

9

db.execSQL("CREATE TRIGGER fk_empdept_deptid " +

    " BEFORE INSERT "+

    " ON "+employeeTable+

     

    " FOR EACH ROW BEGIN"+

    " SELECT CASE WHEN ((SELECT "+colDeptID+" FROM "+deptTable+" _

    WHERE "+colDeptID+"=new."+colDept+" ) IS NULL)"+

    " THEN RAISE (ABORT,'Foreign Key Violation') END;"+

    "  END;");

执行SQL语句

现在让我们开始执行基本的SQL语句。您可以执行任何SQL语句,这不是一个查询,无论是插入,删除,更新或任何使用db.execSQL(String statement)方法一样。当我们创建数据库表时可以这样:

1

2

db.execSQL("CREATE TABLE "+deptTable+" ("+colDeptID+ " INTEGER PRIMARY KEY , "+

    colDeptName+ " TEXT)");

插入记录

我们使用下面的代码在数据库Dept表中插入记录:

1

2

3

4

5

6

7

8

9

10

SQLiteDatabase db=this.getWritableDatabase();

 ContentValues cv=new ContentValues();

   cv.put(colDeptID, 1);

   cv.put(colDeptName, "Sales");

   db.insert(deptTable, colDeptID, cv);

 

   cv.put(colDeptID, 2);

   cv.put(colDeptName, "IT");

   db.insert(deptTable, colDeptID, cv);

   db.close();

注意,我们需要调用this.getWritableDatabase()打开数据库连接进行读写。ContentValues.put有两个参数Column Name 和 value,在执行完语句后关闭数据库是一个很好的做法。

更新值

我们有两种方式执行一个update语句:

1. 执行 db.execSQL

2. 执行 db.update

 

1

2

3

4

5

6

7

8

9

10

public int UpdateEmp(Employee emp)

  {

   SQLiteDatabase db=this.getWritableDatabase();

   ContentValues cv=new ContentValues();

   cv.put(colName, emp.getName());

   cv.put(colAge, emp.getAge());

   cv.put(colDept, emp.getDept());

   return db.update(employeeTable, cv, colID+"=?",

    new String []{String.valueOf(emp.getID())});  

  }

update方法有以下参数:

1. String Table: 需要更新的表

2. ContentValues cv: 新的值

3. String where clause: WHERE子句制定更新的记录

4. String[] args: WHERE 子句参数

删除行

我们有两种方式执行delete语句:

1. 执行 db.execSQL

2. 执行 db.delete方法:

 

 

1

2

3

4

5

6

public void DeleteEmp(Employee emp)

  {

   SQLiteDatabase db=this.getWritableDatabase();

   db.delete(employeeTable,colID+"=?", new String [] {String.valueOf(emp.getID())});

   db.close();

  }

delete方法的参数和update方法一样。

执行查询

有两种方法执行查询:

1. 执行 db.rawQuery

2. 执行 db.query

执行一个原始的查询得到所有部门:

1

2

3

4

5

6

7

8

Cursor getAllDepts()

  {

   SQLiteDatabase db=this.getReadableDatabase();

   Cursor cur=db.rawQuery("SELECT "+colDeptID+" as _id,

    "+colDeptName+" from "+deptTable,new String [] {});

    

   return cur;

  }

rawQuery方法有两个参数:

1. String query:select语句

2. String[] selection args:select语句中WHERE子句的参数。

注意

1.查询结果返回游标对象。

2.在一个 select 语句中,如果表的主键列(ID列)有一个非_id的名称,那么你必须使用SELECT [列名] as _id,因为游标对象总是认为主键列的名称为_id,否则会抛出一个异常。

执行查询的另一种方法是,使用db.query方法。从视图中查询选择某个部门的所有员工:

 

 

1

2

3

4

5

6

7

8

public Cursor getEmpByDept(String Dept)

  {

   SQLiteDatabase db=this.getReadableDatabase();

   String [] columns=new String[]{"_id",colName,colAge,colDeptName};

   Cursor c=db.query(viewEmps, columns, colDeptName+"=?",

    new String[]{Dept}, null, null, null);

   return c;

  }

db.query有如下参数:

1. String Table Name: 数据表名称

2. String [ ] columns: 需要查询的列

3. String WHERE clause: where 子句,如果没有,可以传递null

4. String [ ] selection args: WHERE子句的参数

5. String Group by: 指定group by 子句

6. String Having: 指定HAVING子句

7. String Order By by: 指定Order By子句

游标管理

查询记录集返回在Cursor对象里,使用游标时有一些公共的方法:

boolean moveToNext(): 在记录集里将游标移到下一条记录,如果超过了最后一行则返回false.

boolean moveToFirst(): 将游标移到第一行,如果记录集为空则返回false.

boolean moveToPosition(int position): 移动游标到指定位置,如果位置不可达,则返回false

boolean moveToPrevious(): 将游标移到上一行,如果超过了第一行则返回false

boolean moveToLast(): 将游标移到最后一行,如果记录集为空则返回false.

还有一些检查游标位置的有用方法:boolean isAfterLast(), isBeforeFirst, isFirst, isLast 和 isNull(columnIndex)。此外,如果是只有一行的结果集,你需要检索的某些列的值,你可以这样做:

1

2

3

4

5

6

7

8

9

10

public int GetDeptID(String Dept)

  {

   SQLiteDatabase db=this.getReadableDatabase();

   Cursor c=db.query(deptTable, new String[]{colDeptID+" as _id",colDeptName},

    colDeptName+"=?", new String[]{Dept}, null, null, null);

   //Cursor c=db.rawQuery("SELECT "+colDeptID+" as _id FROM "+deptTable+"

   //WHERE "+colDeptName+"=?", new String []{Dept});

   c.moveToFirst();

   return c.getInt(c.getColumnIndex("_id")); 

  }

我们用 Cursor.getColumnIndex(String ColumnName) 得到列的索引号,然后通过Cursor.getInt(int ColumnIndex)得到列的值。

还有,可以用getShort, getString, getDouble, getBlob得到字节数组的值。使用完游标后用close()关闭是一个好习惯。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值