SQLiteDatabase跟SQLiteOpenHelper

来源:互联网 发布:心事谁人知二胡 编辑:程序博客网 时间:2024/05/11 12:04

http://www.ibm.com/developerworks/cn/opensource/os-cn-sqlite/

1、查询。

public Cursor query (String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
查询返回一个Cursor,这里用法例如
Cursor cursor = db.query("user", new String[]{"id","name"}, "id=?", new String[]{"1"}, null, null, null);
第一个参数为数据表,第二个参数为你要查询的列名,第三个参数相当于一个索引,第四个参数为第三个参数的参数,上面的代码的sql语法为
select id,name from user where id=1;
ParameterstableThe table name to compile the query against.columnsA list of which columns to return. Passing null will return all columns, which is discouraged to prevent reading data from storage that isn't going to be used.selectionA filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.selectionArgsYou may include ?s in selection, which will be replaced by the values from selectionArgs, in order that they appear in the selection. The values will be bound as Strings.groupByA filter declaring how to group rows, formatted as an SQL GROUP BY clause (excluding the GROUP BY itself). Passing null will cause the rows to not be grouped.havingA filter declare which row groups to include in the cursor, if row grouping is being used, formatted as an SQL HAVING clause (excluding the HAVING itself). Passing null will cause all row groups to be included, and is required when row grouping is not being used.orderByHow to order the rows, formatted as an SQL ORDER BY clause (excluding the ORDER BY itself). Passing null will use the default sort order, which may be unordered.

2、改.

public int update (String table, ContentValues values, String whereClause, String[] whereArgs)
return mSQLiteDatabase.update(DB_TABLE, args, KEY_WHAT + "=" + rowId, null) > 0;
用法例如上面这句,第一个为表名,第二个参数为你要更新的列的新值,第三个参数为要更新的是哪个列,
update table set KEY_WHAT=args where KEY_WHAT=“rowId”
update test.t_person set FAge=20 where FName='lau' (把FName='lau'的那个FAge设置为20)
Convenience method for updating rows in the database.

Parameters
table the table to update in
values a map from column names to new column values. null is a valid value that will be translated to NULL.
whereClause the optional WHERE clause to apply when updating. Passing null will update all rows.

Returns
the number of rows affected
 
 
插入:
long android.database.sqlite.SQLiteDatabase.insert(String table,String nullColumnHack,ContentValues values)
long android.database.sqlite.SQLiteDatabase.insert(String table,String nullColumnHack,ContentValues values)
Convenience method for inserting a row into the database.
Parameters:
table the table to insert the row into
nullColumnHack optional; may be null. SQL doesn't allow inserting a completely empty row without naming at least one column name. If your providedvalues is empty, no column names are known and an empty row can't be inserted. If not set to null, thenullColumnHack parameter provides the name of nullable column name to explicitly insert a NULL into in the case where yourvalues is empty.
values this map contains the initial column values for the row. The keys should be the column names and the values the column values
Returns:
the row ID of the newly inserted row, or -1 if an error occurred

nullColumnHack:当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),为了防止这种情况,我们要在这里指定一个列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。
DBOpenHelper.java代码

package com.lau;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;public class DBOpenHelper extends SQLiteOpenHelper{    private static final int DB_VERSION = 1;    private static final String DB_TABLE = "sql_table";     private static final String KEY_ID = "_id";    private static final String KEY_NUM = "num";    private static final String KEY_DATA = "data";        public DBOpenHelper(Context context, String name) {        this(context, name, null, DB_VERSION);    }        public DBOpenHelper(Context context, String name, int version) {        this(context, name, null, version);    }       public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {        super(context, name, factory, version);        // TODO Auto-generated constructor stub    }       @Override    public void onCreate(SQLiteDatabase db) {        // TODO Auto-generated method stub        String sql = "CREATE TABLE " + DB_TABLE + " ( " + KEY_ID + " INTEGER PRIMARY KEY, " + KEY_NUM + " INTEGER, " + KEY_DATA + " TEXT " + ")";        db.execSQL(sql);    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        // TODO Auto-generated method stub        db.execSQL("DROP TABLE IF EXISTS notes");        onCreate(db);    }}

HelloDBHelperActivity.java代码

package com.lau;import android.app.Activity;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;public class HelloDBHelperActivity extends Activity {    /** Called when the activity is first created. */    private static final String DB_NAME = "SQLITE_DB.db";//数据库名    private static final String DB_TABLE = "sql_table";     private static final String KEY_ID = "_id";    private static final String KEY_NUM = "num";    private static final String KEY_DATA = "data";    private Context mContext;    private SQLiteDatabase mLiteDatabase;    private DBOpenHelper mDbOpenHelper;    private EditText et_num;    private EditText et_data;    private Button btn_open;    private Button btn_insert;    private Button btn_query;        @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        et_num = (EditText)findViewById(R.id.et_num);        et_data = (EditText)findViewById(R.id.et_data);        btn_open = (Button)findViewById(R.id.btn_open);        btn_insert = (Button)findViewById(R.id.btn_insert);        btn_query = (Button)findViewById(R.id.btn_query);        btn_open.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO Auto-generated method stub                openDB();            }        });            btn_insert.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO Auto-generated method stub                int num = Integer.parseInt(et_num.getText().toString());                String data = et_data.getText().toString();                insertData(num, data);            }        });               btn_query.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                // TODO Auto-generated method stub                querryData();            }        });    }    public void openDB() {        mDbOpenHelper = new DBOpenHelper(getApplicationContext(), DB_NAME);        mLiteDatabase = mDbOpenHelper.getWritableDatabase();    }     public void closeDB() {        mLiteDatabase.close();    }       public long insertData(int num, String data) {        ContentValues values = new ContentValues();        values.put(KEY_NUM, num);        values.put(KEY_DATA, data);        return mLiteDatabase.insert(DB_TABLE, KEY_ID, values);    }       public boolean deleteData(int rowId) {        return mLiteDatabase.delete(DB_TABLE, KEY_ID + "=" + rowId, null) > 0;    }        public void querryData() {//     Cursor cursor = mLiteDatabase.query(DB_TABLE, new String[]{KEY_ID, KEY_NUM, KEY_DATA}, "id=?", //             new String[]{"1"}, null, null, null);        Cursor cursor = mLiteDatabase.query(DB_TABLE, new String[] {KEY_NUM}, null, null, null, null, null);//        mSQLiteDatabase.query(true, DB_TABLE, new String[] { KEY_ID, KEY_NUM, KEY_DATA }, KEY_ID + "=" + rowId, null, null, null, null, null);        while(cursor.moveToNext()){            int num = cursor.getInt(cursor.getColumnIndex(KEY_NUM));            System.out.println(num);        }    }}


main.xml代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    >    <TextView         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:text="num:"        />    <EditText        android:id="@+id/et_num"        android:layout_width="fill_parent"        android:layout_height="wrap_content"         />    <TextView         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:text="data"        />    <EditText        android:id="@+id/et_data"        android:layout_width="fill_parent"      android:layout_height="wrap_content"         />    <Button         android:text="Open"         android:id="@+id/btn_open"         android:layout_width="fill_parent"         android:layout_height="wrap_content"        />     <Button         android:text="Insert"         android:id="@+id/btn_insert"         android:layout_width="fill_parent"         android:layout_height="wrap_content"        />     <Button         android:text="Query"         android:id="@+id/btn_query"         android:layout_width="fill_parent"         android:layout_height="wrap_content"        /> </LinearLayout>








http://blog.csdn.net/jin868/article/details/5961263



一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。SQLite具有以下五种数据类型:

1.NULL:空值。
2.INTEGER:带符号的整型,具体取决有存入数字的范围大小。
3.REAL:浮点数字,存储为8-byte IEEE浮点数。
4.TEXT:字符串文本。
5.BLOB:二进制对象。


但实际上,sqlite3也接受如下的数据类型:
smallint 16 位元的整数。
interger 32 位元的整数。
decimal(p,s) p 精确值和 s 大小的十进位整数,精确值p是指全部有几个数(digits)大小值,s是指小数点後有几位数。如果没有特别指定,则系统会设为 p=5; s=0 。
float  32位元的实数。
double  64位元的实数。
char(n)  n 长度的字串,n不能超过 254。
varchar(n) 长度不固定且其最大长度为 n 的字串,n不能超过 4000。
graphic(n) 和 char(n) 一样,不过其单位是两个字元 double-bytes, n不能超过127。这个形态是为了支援两个字元长度的字体,例如中文字。
vargraphic(n) 可变长度且其最大长度为 n 的双字元字串,n不能超过 2000
date  包含了 年份、月份、日期。
time  包含了 小时、分钟、秒。
timestamp 包含了 年、月、日、时、分、秒、千分之一秒。

datetime 包含日期时间格式,必须写成'2010-08-05'不能写为'2010-8-5',否则在读取时会产生错误!

Sqlite常用数据类型,

这句话本身就有问题,因为:SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中, 无论这列声明的数据类型是什么(只有自动递增Integer Primary Key才有用). 对于SQLite来说对字段不指定类型是完全有效的. 如:

Create Table ex3(a, b, c);

即使SQLite允许忽略数据类型, 但是仍然建议在你的Create Table语句中指定数据类型. 因为数据类型对于你和其他的程序员交流, 或者你准备换掉你的数据库引擎是非常有用的. SQLite支持常见的数据类型, 如:

SQL代码
  1. CREATE TABLE ex2(    
  2. a VARCHAR(10),    
  3. b NVARCHAR(15),   
  4. c TEXT,    
  5. d INTEGER,   
  6. e FLOAT,   
  7. f BOOLEAN,    
  8. g CLOB,    
  9. h BLOB,    
  10. i TIMESTAMP,   
  11. j NUMERIC(10,5),    
  12. k VARYING CHARACTER (24),    
  13. l NATIONAL VARYING CHARACTER(16)   
  14. );

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。



 

 

一些常用语句

1.增
insert into test.t_person(FName, FAge) value('lau', 20)

2.删
delete from test.t_person    (清空表,不是删除表)
delete from test.t_person where FName='lau'

 

3.改
update test.t_person set FAge=10   (把所有FAge设置为10)
update test.t_person set FAge=20 where FName='lau' (把FName='lau'的那个FAge设置为20

 


4.查
select * from test.t_person
select FName,FAge from test.t_person      (可以加,号来之列多列)
select * from test.t_person where FAge>20 
select * from test.t_person where FName like '%l%'    (查看FName中有l的条目)
select * from test.t_person where FName like 'l%' or/and FName like '%u%' (查看FName中以l 或者/并且 开头的的条目)
select * from test.t_person where FAge between 10 and 20   (查看FAge中以>10并且<20 开头的的条目)
select sum(FAge) from test.t_person
select avg(FAge) from test.t_person
select max(FAge) from test.t_person
select min(FAge) from test.t_person
select sum(FAge),avg(FAge),max(FAge),min(FAge) from test.t_person
select count(*) from test.t_person
select * from tset.t_person order by FAge asc/desc  升序/降序 排列

 

CREATE TABLE  `test`.`t_person` (

 `FName` varchar(45) NOT NULL DEFAULT '',

 `FAge` int(10) unsigned NOT NULL DEFAULT '0'

)ENGINE=InnoDB DEFAULT CHARSET=latin1;

 

 

 

 

 

遇有未知结构的数据库时,可以通过以下方法来或许数据库中详细信息。

1.   .table命令  可以查询当前数据库中所有的表名

2.   select * from sqlite_master WHERE type = "table";   可以查询到当前数据库中所有表的详细结构信息

[test@localhost ~]$ sqlite3 py.db

SQLite version 3.6.17

Enter ".help" for instructions

Enter SQL statements terminated with a ";"

sqlite> .table

py_phrase   py_pinyin   py_shengmu

sqlite> select * from sqlite_master WHERE type = "table";

table|py_pinyin|py_pinyin|2|CREATE TABLE py_pinyin (pinyin TEXT PREMARY KEY)

table|py_shengmu|py_shengmu|3|CREATE TABLE py_shengmu (shengmu TEXT PREMARY KEY)

table|py_phrase|py_phrase|4|CREATE TABLE py_phrase (

ylen INTEGER,

y0 INTEGER, y1 INTEGER, y2 INTEGER, y3 INTEGER, yx TEXT,

s0 INTEGER, s1 INTEGER, s2 INTEGER, s3 INTEGER,

phrase TEXT,

freq INTEGER, user_freq INTEGER)

sqlite>

  1. 1)创建数据库文件:  
  2.    >SQLite3 d:\test.db 回车  
  3.    就生成了一个test.db在d盘。  
  4.    这样同时也SQLite3挂上了这个test.db  
  5.    2)   
  6.    用.help可以看看有什么命令  
  7.    >.help 回车即可  
  8.    3)可以在这里直接输入SQL语句创建表格 用;结束,然后回车就可以看到了  
  9.    4)看看有创建了多少表  
  10.    >.tables   
  11.    5)看表结构  
  12.    >.schema 表名  
  13.    6)看看目前挂的数据库  
  14.    >.database 
  15.    7)如果要把查询输出到文件  
  16.    >.output 文件名  
  17.    > 查询语句;  
  18.    查询结果就输出到了文件c:\query.txt   
  19.  
  20.    把查询结果用屏幕输出  
  21.    >.output stdout  
  22.  
  23.    8)把表结构输出,同时索引也会输出  
  24.      .dump 表名  
  25.    9)退出  
  26.    >.exit 或者.quit
  27. 普通SQL操作,通用标准SQL语句。

 

关于数据库更改,可以用ALTER语句:http://www.w3school.com.cn/sql/sql_alter.asp

增加列:

ALTER TABLE table_name ADD column_name dataType;

删除列:

ALTER TABLE table_name DROP COLUMN column_name;

/**
* SQLite3支持的数据类型:
*        NULL:         表示一个NULL值
*        INTEGER:     用来存储一个整数,根据大小可以使用1,2,3,4,6,8位来存储.
*        REAL:         IEEE 浮点数
*        TEXT:         按照字符串来存储
*        BLOB:         按照二进制值存储,不做任何改变.
* 实际上,SQLite是无类型的!你几乎可以将任意类型的数据存储到任意表的任意列而
* 无视其类型限制,只有一种例外:定义为INTEGER PRIMARY KEY的字段只能存储 整数,
* 当向这种字段中保存除整数以外的数据时,将会产生错误。
*/
/**
* SQLiteOpenHelper:
*         是一个抽象类,用于数据库的创建和版本的管理。要使用它必须实现它的
*         onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase, int, int)方法。
*         另外还有两个受保护方法不是必须实现的:
*             onDowngrade(SQLiteDatabase, int, int)数据库降级时调用;
*             onOpen(SQLiteDatabase) 数据库成功打开时首先被调用;
*         通过getWritableDatabase()和getReadableDatabase()可以获取数据库实例。
* SQLiteDatabase:
*         封装了一些操作数据库的API。使用它能实现基本的CRUD操作。
* 因此,要使用SQLite必须自己实现一个类,继承自SQLiteOpenHelper。
*/
class MyDatabase extends SQLiteOpenHelper
{
    private SQLiteDatabase wdb = null;
    private SQLiteDatabase rdb = null;
    public MyDatabase(Context context/*上下文环境*/, String name/*数据库名称*/,
                      CursorFactory factory/*null*/, int version/*版本号,1*/) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        /**
         * 在SQLite中,必须要创建一个表才可以创建出数据库。
         * 但有时候在创建数据库之前并没有确定建什么表,这里采取建一张没有意义的表来创建数据库。
         */
        try{
            //PRIMARY KEY AUTOINCREMENT表示该字段为自动增加的主键
            db.execSQL("CREATE TABLE temp(id INTEGER PRIMARY KEY AUTOINCREMENT)");
        }catch(SQLException sqlex){
            sqlex.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //用于数据库版本升级处理
    }
   
    public boolean CreateTable(String tablename, String[] fields, String[] types)
    {
        if(fields.length == 0) return false;
        /**
         * 首先判断数据库中表名是否已存在
         * 如果已经存在,则删除原来的表
         */
        //获取一个可读数据库,或者说是以可读的方式打开数据库
        rdb = getReadableDatabase();
        if(rdb == null)
        {
            return false;
        }
        else
        {
            //表sqlite_master是一个特殊的表,由SQLite自动维护,保存其他表的相关信息
            Cursor cur = rdb.query( "sqlite_master",                //表名
new String[]{"name"}, //列名
                                                   "name = ?",                      //where从句,"=="和"="都可以比较
                                                   new String[]{tablename},  //对上面的问号赋值
                                                   null,                                  //groupBy从句
                                                   null,                                  //having从句
                                                   "name desc");                  //orderBy从句
            if(cur.getCount() > 0)
            {
                try{
                    rdb.execSQL("DROP TABLE " + tablename);//删除数据库中的指定的数据表
                }catch(SQLException sqlex){
                    sqlex.printStackTrace();
                    return false;
                }
            }
            cur.close();
            rdb.close();
        }
       
        //创建表,先构造一个创建表的SQL语句
        String sql = "CREATE TABLE " + tablename + "(";
        if(types == null)
        {
            for(int i=0;i<fields.length;i++)
            {   
                if(i < fields.length-1) sql += fields[i] + ", ";
                if(i == fields.length-1) sql += fields[i];
            }
        }
        else
        {
            for(int i=0;i<fields.length;i++)
            {
                String type = types[i];           
                if(i < fields.length-1) sql += fields[i] + " " + type + ",";
                if(i == fields.length-1) sql += fields[i] + " " + type;
            }
        }
        sql += ")";
        //获取一个可写数据库,或者说是以可写的方式打开数据库
        wdb = getWritableDatabase();
        if(wdb == null)
        {
            return false;
        }
        else
        {
            try{
                wdb.execSQL(sql);
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return false;
            }
            wdb.close();
        }
        return true;
    }
   
    //由于SQLite是无类型的数据库,你几乎可以将任意类型的数据存储到任意表的任意列,只有一种例外
    //因此将所有的值全部转换成字符串存储是可行的
    public boolean InsertData(String tablename, String[] fields, String[] values)
    {
        if(values.length == 0 || fields.length == 0) return false;
        if(values.length != fields.length) return false;
       
        ContentValues contentValues = new ContentValues();
        for(int i=0;i<values.length;i++)
        {           
            contentValues.put(fields[i], values[i]);
        }
        wdb = getWritableDatabase();
        if(wdb == null)
        {
            return false;
        }
        else
        {
            /**
             * 关于insert方法的第2个参数,官方解释为:
             * optional; may be null. SQL doesn't allow inserting a completely empty row
             * without naming at least one column name. If your provided values is empty,
             * no column names are known and an empty row can't be inserted. If not set
             * to null, the nullColumnHack parameter provides the name of nullable column
             * name to explicitly insert a NULL into in the case where your values is empty.
             */
            wdb.insert(tablename, null, contentValues);
            wdb.close();
        }
        return true;
    }
   
    public Cursor SelectData(String tablename, String[] fields, String where,
            String[] whereArgs, String groupby, String having, String orderby)
    {
        rdb = getReadableDatabase();
        if(rdb == null) return null;
        Cursor cursor = rdb.query(  tablename,     //表名
                                                    fields,              //列名
                                                    where,             //where从句, ex:"age>?"
                                                    whereArgs,      //对where从句中的问号赋值
                                                    groupby,          //groupBy从句
                                                    having,            //having从句
                                                    orderby );        //orderBy从句
        //rdb.close();//这里不能关闭,关闭的话返回的cursor里将没有数据。害我调了半天。
        return cursor;
    }

 

/**
     * SQLite不直接支持删除列和更改列名
     * 只能通过间接方式实现,以删除列为例:
     * 假设有一个表table有id、name、age三列,要删除其中的age列
     * 1,重命名table为temptable
     * 2,新建表:CREATE TABLE table(id INTEGER PRIMARY KEY, name TEXT);
     * 3,将temptable中的数据除age列外全部copy到table中:INSERT INTO table SELECT id, name FROM tmptable;
     * 4,将temptable表删除:DROP TABLE tmptable;
     *
     * SQLite支持表名的修改和增加列
     * 1,修改表名:ALTER TABLE oldtablename RENAME TO newtablename;
     * 2,增加列:ALTER TABLE tablename ADD COLUMN fieldname  fieldtype;
     *
     * 注:RENAME TO语法用于重命名表名[database-name.]table-name 到new-table-name 。
     *     这一命令不能用于在附加数据库之间移动表,只能在同一个数据库中对表进行重命名。
     *     若需要重命名的表有触发器或索引,在重命名后它们依然属于该表。但若定义了视图,
     *     或触发器执行的语句中有提到 表的名字,则它们不会被自动改为使用新的表名。若要
     *     进行这一类的修改,则需手工撤销并使用新的表名重建触发器或视图。
     *    
     *     ADD [COLUMN]语法用于在已有表中添加新的字段。新字段总是添加到已有字段列表的
     *     末尾。fieldname 可以是CREATE TABLE中允许出现的任何形式,且须符合如下限制:
     *             字段不能有主键或唯一约束。
     *             字段不能有这些缺省值:CURRENT_TIME, CURRENT_DATE或CURRENT_TIMESTAMP
     *             若定义了NOT NULL约束,则字段必须有一个非空的缺省值。
     *     ALTER TABLE语句的执行时间与表中的数据量无关,它在操作一个有一千万行的表时的
     *     运行时间与操作仅有一行的表时是一样的。
     *     在对数据库运行ADD COLUMN之后,该数据库将无法由SQLite 3.1.3及更早版本读取,
     *     除非运行VACUUM 命令。
     */
    //删除一列,该函数尚未测试
    public void DeleteField(String tablename, String field)
    {
        String[] oldColumns = null;//删除前的列名
        String[] newColumns = null;//删除后的列名
       
        //先获取该表的列数量和列名
        rdb = getReadableDatabase();
        if(rdb == null)
        {
            return;
        }
        else
        {
            //不知道有没有更好的方法获取列名?
            Cursor cursor = rdb.query(tablename, null, null, null, null, null, null);
            if(cursor.getCount() == 0) return;
           
            int nColumnCount = cursor.getColumnCount();//获取该表中列的数量
            if(nColumnCount == 1)
            {
                //如果表中只有一列,删除表
                try{
                    rdb.execSQL("DROP TABLE tablename");
                }catch(SQLException sqlex){
                    sqlex.printStackTrace();
                    return;
                }
                return;
            }
            //判断表中有没有所要删除的列名
            boolean b = false;
            for(int i=0;i<nColumnCount;i++)
            {
                if(field.equals(cursor.getColumnName(i)))
                {
                    b = true;
                    break;
                }
            }
            if(!b) return;
           
            oldColumns = new String[nColumnCount];
            newColumns = new String[nColumnCount-1];
            int j = 0;
            for(int i=0;i<nColumnCount;i++)
            {
                oldColumns[i] = cursor.getColumnName(i);
                if(!oldColumns[i].equals(field)) newColumns[j++] = oldColumns[i];
            }
            cursor.close();
        }
        rdb.close();
       
        wdb = getWritableDatabase();
        if(wdb == null)
        {
            return;
        }
        else
        {
            try{
                wdb.execSQL("ALTER TABLE " + tablename + " RENAME TO tmptable;");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                String sql = "CREATE TABLE " + tablename + "(" + newColumns[0];
                for(int i=1;i<newColumns.length;i++)
                {
                    sql += ", " + newColumns[i];
                }
                sql += ")";
                wdb.execSQL(sql);
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                String fields = newColumns[0];
                for(int i=1;i<newColumns.length;i++)
                {
                    fields += ", " + newColumns[i];
                }
                wdb.execSQL("INSERT INTO " + tablename +" SELECT " + fields + " FROM tmptable");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                wdb.execSQL("DROP TABLE tmptable");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            wdb.close();
        }
    }
   
    //添加一列,该函数尚未测试
    public void InsertField(String tablename, String field, String type)
    {
        if(type == null) type = "";
        wdb = getWritableDatabase();
        if(wdb == null)
        {
            return;
        }
        else
        {
            try{
                wdb.execSQL("ALTER TABLE " + tablename + " ADD COLUMN " + field + " " + type);
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            wdb.close();
        }
    }
   
    //修改列名,方法与删除列一致,可以顺便修改该列的类型,该函数尚未测试
    public void RenameField(String tablename, String oldFieldName, String newFieldName, String type)
    {
        String[] newColumns = null;
        if(type == null) type = "";
       
        rdb = getReadableDatabase();
        if(rdb == null)
        {
            return;
        }
        else
        {
            Cursor cursor = rdb.query(tablename, null, null, null, null, null, null);
            if(cursor.getCount() == 0) return;
           
            int nColumnCount = cursor.getColumnCount();

            //判断表中有没有所要修改的列名
            boolean b = false;
            for(int i=0;i<nColumnCount;i++)
            {
                if(oldFieldName.equals(cursor.getColumnName(i)))
                {
                    b = true;
                    break;
                }
            }
            if(!b) return;
           
            newColumns = new String[nColumnCount];
            for(int i=0;i<nColumnCount;i++)
            {
                if(cursor.getColumnName(i).equals(oldFieldName)) newColumns[i] = newFieldName;
                else newColumns[i] = cursor.getColumnName(i);
            }
            cursor.close();
        }
        rdb.close();
       
        wdb = getWritableDatabase();
        if(wdb == null)
        {
            return;
        }
        else
        {
            try{
                wdb.execSQL("ALTER TABLE " + tablename + " RENAME TO tmptable;");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                String sql = "CREATE TABLE " + tablename + "(" + newColumns[0];
                for(int i=1;i<newColumns.length;i++)
                {
                    sql += ", " + newColumns[i];
                }
                sql += ")";
                wdb.execSQL(sql);
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                wdb.execSQL("INSERT INTO " + tablename +" SELECT * FROM tmptable");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            try{
                wdb.execSQL("DROP TABLE tmptable");
            }catch(SQLException sqlex){
                sqlex.printStackTrace();
                return;
            }
            wdb.close();
        }
    }
    /**
     * 关于删除和修改数据,包括添加数据,都可以使用execSQL方法实现,需要自己构造SQL语句。
     * 也可以使用SQLiteDatabase提供的delete和updata方法:
     * public int delete (String table,                 //表名
     *                            String whereClause,    //where从句,可以包含"?"通配符
     *                            String[] whereArgs)      //对where从句中问号的赋值
     * public int update (String table,                  //表名
     *                             ContentValues values,  //a map from column names to new column values
     *                             String whereClause,      //where从句,可以包含"?"通配符
     *                             String[] whereArgs)       //对where从句中问号的赋值
     */
    public void UpdateData(String sql)
    {
        wdb = getWritableDatabase();
       
        if(wdb == null) return;
        try{
            wdb.execSQL(sql);
        }catch(SQLException sqlex){
            sqlex.printStackTrace();
            return;
        }
        wdb.close();
    }
}

原创粉丝点击