Android的数据存储(基础)之SQLite

一、数据库基础

1、安装SQLite

官网下载所需的数据库插件。下载完成后,解压到C:\sqlite目录下,把路径配置到环境变量--->系统变量的path下,即可。
检验是否安装成功,如下图,出现数据库版本说明安装成功。

sqlite.png

安装后可直接在命令行输入数据库操作命令,查看数据库内容,没有安装的话,需要在AndroidStudio中用adb命令进入所在目录,查看数据库内容。所以,安装不安装影响不大,反正都可以用。

2、数据库基本命令
创建数据库 sqlite3  database_name.db
创建表 CREATE TABLE  table_name(column_name_1 data_type_1,column_name_2  data_type_2,...);
在数据库中插入数据 INSERT INTO  table_name(column_name_1,column_name_2,...) VALUES (values_1,values_2,...);
读取数据库中的数据 SELECT columns FROM table_name; (从数据库中选择定数据)
database.png

语句解析:

jiexi.png

SQL语句特别提示:
1)所有数据库语句都以“ ; ”(分号)结束,如果没有“ ; ”的情况下会出现“ ... ”提示用户继续输入内容。
2)数据库关键字不区分大小写,但是为了方便查看,数据库结构化语句一般是用大写

SQL的其他命令(注意,这些命令不用" ;"结束,并且严格区分大小写)
这些命令不用记忆,当使用时,直接.help即可,查找自己所需的命令
.header <on|off>
.help 帮助命令,可以查看所有的命令
.mode <mode> 设置输出模式(asci,csv,column,html,insert,line,list,tabs,tcl)
.open <filename> 关闭当前数据库,打开fliename对应的数据库
.quit 退出命令行
.schema >table_name> 显示创建表的语句
.tables 列出表名

二、Android中使用数据库

官方文档
数据库使用场景:数据量大,数据有一定的格式

1、首先创建数据库前需明确创建数据库的名字、表名、以及各列的名字及数据类型,(ps,补充数据库的数据类型)

NULL null空
INTEGER 整型
REAL 浮点型
TEXT 文本类型
BOLB 二进制类型

2、Contract类,存储数据库的结构即架构,将数据库中的表名、列名抽象成常量定义在Contract类中。Contract类的优点

1)后期的更新维护会更方便
2)生成SQL指令时,避免拼写错误
3)为了定义存储数据库结构,即架构,并且规定去哪里查询数据库常量

创建Contract类的步骤:
a、创建外部类XxxContract
b、创建内部类XxxEntry实现BaseColumns接口
c、为表名和列名定义字符串常量

具体的代码:

public final class BookContract {

    private BookContract(){}

  //内部类BookEntry ,为数据库中表的每一列定义常量值
    public static final class BookEntry implements BaseColumns{
        public static final String TABLE_NAME = "book";
        public static final String _ID = BaseColumns._ID; // 自增长的id
        public static final String COLUMN_BOOK_AUTHOR = "author";
        public static final String COLUMN_BOOK_NAME = "name";
        public static final String COLUMN_BOOK_PRICE = "price";
        public static final String COLUMN_BOOK_PAGES = "pages";
    }
}
3、创建数据库的步骤:

1)创建一个类继承SQLiteOpenHelper
2)创建数据库名字和数据库版本的常量
3)创建构造函数
4)实现onCreate()方法
5)实现onUpgrade()方法

public class MySQLiteOpenHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME = "bookStore.db";
    public static final int DATABASE_VERSION = 1;

    //创建表
    private static final String SQL_CREATE_BOOKSTORE_TABLE = "CREATE TABLE" +
            BookContract.BookEntry.TABLE_NAME + "(" +
            BookContract.BookEntry._ID + "INTEGER PRIMARY KEY AUTOINCREMENT," +
            BookContract.BookEntry.COLUMN_BOOK_NAME + "TEXT," +
            BookContract.BookEntry.COLUMN_BOOK_AUTHOR + "TEXT" +
            BookContract.BookEntry.COLUMN_BOOK_PAGES + "INTEGER" +
            BookContract.BookEntry.COLUMN_BOOK_PRICE + "REAL"
            + ");";
    //删除表
    private static final String SQL_DELETE_ENTRIES = "DROP TABLE IF EXITS" + BookContract.BookEntry.TABLE_NAME;

    /**
     * 构造函数四个参数:
     * 第一个参数:Contxt,上下文对象,对数据库进行操作
     * 第二个参数:数据库名,创建数据库时使用的名称
     * 第三个参数:允许在查询数据时返回一个自定义的Cursor,普通情况下传入null
     * 第四个参数:当前数据库版本号,可用于数据库升级操作
     */

    public MySQLiteOpenHelper(Context context, SQLiteDatabase.CursorFactory factory) {
        super(context, DATABASE_NAME, factory, DATABASE_VERSION );
    }
    

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        sqLiteDatabase.execSQL(SQL_CREATE_BOOKSTORE_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    
        sqLiteDatabase.execSQL(SQL_DELETE_ENTRIES);
        onCreate(sqLiteDatabase);
    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        onUpgrade(db, oldVersion, newVersion);
    }
}

至此,已经创建了bookStore.db数据库,创建了表book,可通过adb命令来查看数据库内容,在AndroidStudio Terminal中输入adb shell进入设备控制台,然后用cd命令进入data/data/packagename(你自己的包名)可以看到自己建立的数据库,然后用sqlite3 数据名,打开数据库,此时就可以对数据库进行管理了,.table查看当前的表,.schema查看下建表语句

database.png
4.对数据库进行增删改查操作

为了访问数据库bookStore.db,需实例化SQLiteOpenHelper的子类:

 new MySQLiteOpenHelper(context);

Android中SQLiteDatabase提供了对应的增删改查方法。

1)在数据库中插入数据

通过ContentValues对象的put()方法,放入要存储的数据,然后用insert()方法插入到数据库中。

      public void insert(Book book){
        //获取数据库对象
        SQLiteDatabase db = myHelper.getWritableDatabase();

        ContentValues values = new ContentValues();

        Log.e("SQL",book.getBookAuthor() + "-----" + book.getBookName() + "----"
                + book.getBookPrice() + "------" +book.getPages());
        values.put(BookContract.BookEntry.COLUMN_BOOK_NAME, book.getBookName());
        values.put(BookContract.BookEntry.COLUMN_BOOK_PRICE, book.getBookPrice());
        values.put(BookContract.BookEntry.COLUMN_BOOK_PAGES, book.getPages());
        values.put(BookContract.BookEntry.COLUMN_BOOK_AUTHOR, book.getBookAuthor())  ;

        /*
        insert(String table, String nullColumnHack, ContentValues values)
        参数:String table 要插入数据的表的名称
        String nullColumnHack 我们知道数据库中除主键外其他的值可以为null,此参数表示该表的该字段不能为null,此处传入null表示插入的表的字段值可以为空
        ContentValues values 要插入的数据,是一个数据集
        返回值 long 最新插入的行的ID,如果发生错误,返回-1
        */

        long id = db.insert(BookContract.BookEntry.TABLE_NAME, null, values);
        book.setId(id);
        db.close();
    }

2)从数据库中读取数据
从数据库读取数据,需要使用query()方法,传递需要查询的条件。查询后返回一个Cursor对象
Cursor类:
Cursor代表数据库中各行内容的对象,返回的Cursour对象包含了查询结果的所有内容。注意Cursor使用完毕后必须关闭,否则会出现内存泄漏。

具体使用,示例代码:
查询数据库中的所有数据

 public List<Book> queryAll() {
        SQLiteDatabase db = myHelper.getReadableDatabase();
        Cursor cursor = db.query(BookContract.BookEntry.TABLE_NAME, null, null, null, null, null, null);
        Log.e("SQL", "数据库的数据总数为" + cursor.getCount());

        List<Book> list = new ArrayList<>();
        if (cursor.getCount() > 0) {

            while (cursor.moveToNext()) {
                Book book = new Book();
                book.setBookName(cursor.getString(1));
                book.setBookAuthor(cursor.getString(2));
                book.setBookPrice(cursor.getFloat(3));
                book.setPages(cursor.getInt(4));

                list.add(book);
            }
        }

        cursor.close();
        db.close();
        return list;
    }

根据某个项查询(这里根据book Name来查找

 public List<Book> queryByInput(String[] queryStr) {

        List<Book> books = new ArrayList<>();

        SQLiteDatabase db = myHelper.getReadableDatabase();

        //select name,author from tables where pages= 100
        // 根据查询条件获取具体的列
        String[] projection = new String[]{
                BookContract.BookEntry.COLUMN_BOOK_NAME,
                BookContract.BookEntry.COLUMN_BOOK_AUTHOR,
                BookContract.BookEntry.COLUMN_BOOK_PAGES,
                BookContract.BookEntry.COLUMN_BOOK_PRICE
        };
        String selection = BookContract.BookEntry.COLUMN_BOOK_NAME + "=?";
        String[] selectionArgs = queryStr;

        Cursor cursor = db.query(BookContract.BookEntry.TABLE_NAME, projection, selection, selectionArgs, null, null, null);

        try {

            while (cursor.moveToNext()) {
                Book book = new Book();
                book.setBookName(cursor.getString(cursor.getColumnIndex(BookContract.BookEntry.COLUMN_BOOK_NAME)));
                book.setBookAuthor(cursor.getString(cursor.getColumnIndex(BookContract.BookEntry.COLUMN_BOOK_NAME)));
                book.setBookPrice(cursor.getFloat(cursor.getColumnIndex(BookContract.BookEntry.COLUMN_BOOK_PRICE)));
                book.setPages(cursor.getInt(cursor.getColumnIndex(BookContract.BookEntry.COLUMN_BOOK_PAGES)));

                books.add(book);
            }
        } finally {
            cursor.close();
        }
        return books;

    }

3)删除数据库中的信息
SQL Injection(SQL注入):随着B/S模式应用开发的发展,使用这
种模式编写应用程序的程序员越来越多,但由于程序员的水平及经验参差不齐,相当大一部分程序员在编写代码时没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户提交一段数据库查询代码,根据程序返回的结构,获得某些想得知的数据,这就是所谓的SQL注入。

  public int delete(String name) {

        SQLiteDatabase db = myHelper.getWritableDatabase();
        //  delete(表名,where语句,要查的字段)
        int count = db.delete(BookContract.BookEntry.TABLE_NAME, BookContract.BookEntry.COLUMN_BOOK_NAME + " = ?" , new String[]{name});
//        db.execSQL("DELETE FROM " + BookContract.BookEntry.TABLE_NAME +" WHERE id = " + id + ";");
        Log.e("SQL",BookContract.BookEntry.TABLE_NAME + BookContract.BookEntry.COLUMN_BOOK_NAME + " = ?" + new String[]{name});
        db.close();
        return count;
    }

4)更新数据库
当需要修改数据库中的某些数据时,使用update()方法。update结合了插入与删除语法。

 public int update(Book book,String name) {
        SQLiteDatabase db = myHelper.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(BookContract.BookEntry.COLUMN_BOOK_NAME, book.getBookName());
        values.put(BookContract.BookEntry.COLUMN_BOOK_AUTHOR, book.getBookAuthor());
        values.put(BookContract.BookEntry.COLUMN_BOOK_PRICE, book.getBookPrice());
        values.put(BookContract.BookEntry.COLUMN_BOOK_PAGES, book.getPages());
        int count = db.update(BookContract.BookEntry.TABLE_NAME, values,
                BookContract.BookEntry.COLUMN_BOOK_NAME + " = ?",
                new String[]{name});

        // Log.e("SQL", "update" + book.getId() + book.getBookName() + book.getBookAuthor() + book.getBookPrice() + book.getPages());
        db.close();
        return count;
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • “蹭”,这是个半贬不褒的词,虽然如此,但其实很多人都有过各种蹭的经历。比如大学时没订上喜爱老师的课或者它系老师的课...
    米特Dragon阅读 402评论 2 0