SQLite CRUD/原理/升级/降级,加密库SqliteCipher,GreenDao,SQLite损坏与修复

-- SQLite删除表drop;增删改查create,insert,drop,select,update
1.当表中没有任何数据时

 删除表
DROP TABLE MyTable;

 创建表
CREATE TABLE MyTable ...

2.当表中有数据时

 将表名改为临时表
ALTER TABLE MyTable RENAME TO _temp_MyTable;

 创建新表
CREATE TABLE MyTable (....);

 导入数据
INSERT INTO MyTable SELECT .., .. ,“用空来补充原来不存在的数据”  FROM _temp_MyTable;

 删除临时表
DROP TABLE _temp_MyTable;

-- drop,truncate,delete区别:
 1、drop (删除表):删除内容和定义,释放空间。简单来说就是把整个表去掉.以后要新增数据是不可能的,除非新增
一个表。
 drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger)索引(index);依赖于该表的存储过程/函数
将被保留,但其状态会变为:invalid。
 2、truncate (清空表中的数据):删除内容、释放空间但不删除定义(保留表的数据结构)。与drop不同的是,只是清
空表数据而已。
 注意:truncate 不能删除行数据,要删就要把表清空。
 3、delete (删除表中的数据):delete 语句用于删除表中的行。delete语句执行删除的过程是每次从表中删除一行
,并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作。truncate与不带where的delete :
只删除数据,而不删除表的结构(定义)
 4、truncate table 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该
列的种子。如果想保留标识计数值,请改用delete。
  如果要删除表定义及其数据,请使用 drop table 语句。  
 5、对于由foreign key约束引用的表,不能使用truncate table ,而应使用不带where子句的delete语句。由于
truncate table 记录在日志中,所以它不能激活触发器。
 6、执行速度,一般来说: drop> truncate > delete。
 7、delete语句是数据库操作语言(dml),这个操作会放到 rollback segement 中,事务提交之后才生效;如果有相
应的 trigger,执行的时候将被触发。

 truncate、drop 是数据库定义语言(ddl),操作立即生效,原数据不放到 rollback segment 中,不能回滚,操作不
触发 trigger。
- 根据版本号,升级数据库sqlite.回滚rollback.
-- 数据库查询优化:创建索引;如有必要,分库分表。

-- 提升SQLite数据插入效率低、速度慢的方法
 慢速——最粗暴的方法(SQLite的API中直接执行SQL)
 中速——显式开启事务(就是指一组SQL命令,这些命令要么一起执行,要么都不被执行)
 高速——写同步(synchronous)
 极速——执行准备(一种是使用前文提到的函数sqlite3_exec(),该函数直接调用包含SQL语句的字符串;另一种方法就是“执行准备”(类似于存储过程)操作,即先将SQL语句编译好,然后再一步一步(或一行一行)地执行。)
 SQLite插入数据效率最快的方式就是:事务+关闭写同步+执行准备(存储过程),如果对数据库安全性有要求的话,就开启写同步。

> 原生 SQLite
SQLite官网: https://www.sqlite.org/pragma.html#pragma_page_size

数据库MariaDB(腾讯推广的)- https://github.com/MariaDB/server/pull/246
SQLite官网- http://www.sqlite.org/howtocorrupt.html
Android 数据库开发(一)SQLite3概述- http://blog.csdn.net/itachi85/article/details/51649468
  Android、iOS等移动操作系统中的数据库实现也是使用的SQLite3。程序库实现了多数的SQL-92标准,包括事务以及实现原子性、一致性、隔离性和持久性,但它缺失了某些特性,例如它仅部分支持触发器: 支持 FOR EACH ROW 触发器,但不支持 FOR EACH STATEMENT 触发器。尽管它支持大多数复杂查询,但它的ALTER TABLE 功能有所限制:只能添加和重命名列,不能修改或者删除列。因此,当需要修改或者删除列名时只能重新创建表。
  Sqlite修改数据库表名修改、增加字段- http://blog.csdn.net/yujianxiang666/article/details/46724923
SQL语句:Android Sqlite 数据库版本更新,实现SqliteOpenHelper的两个方法 onCreate与onUpgrade;做Android应用,不可避免的会与SQLite打交道。随着应用的不断升级,原有的数据库结构可能已经不再适应新的功能,这时候,就需要对SQLite数据库的结构进行升级了。 SQLite提供了ALTER TABLE命令,允许用户重命名或添加新的字段到已有表中,但是不能从表中删除字段。
 并且只能在表的末尾添加字段,比如,为 Subscription添加两个字段:
 ALTER TABLE Subscription ADD COLUMN Activation BLOB;
 ALTER TABLE Subscription ADD COLUMN Key BLOB;

 另外,如果遇到复杂的修改操作,比如在修改的同时,需要进行数据的转移,那么可以采取在一个事务中执行如下语句来实现修改表的需求。
 1. 将表名改为临时表
         ALTER TABLE Subscription RENAME TO __temp__Subscription;
 2. 创建新表
        CREATE TABLE Subscription (OrderId VARCHAR(32) PRIMARY KEY ,UserName VARCHAR(32) NOT NULL ,ProductId VARCHAR(16) NOT NULL);
 3. 导入数据  
         INSERT INTO Subscription SELECT OrderId, “”, ProductId FROM __temp__Subscription;
  或者  
        INSERT INTO Subscription() SELECT OrderId, “”, ProductId FROM __temp__Subscription;
  * 注意 双引号”” 是用来补充原来不存在的数据的 
  4. 删除临时表  
        DROP TABLE __temp__Subscription;
通过以上四个步骤,就可以完成旧数据库结构向新数据库结构的迁移,并且其中还可以保证数据不会应为升级而流失。

-- SQLite分页查询
Android SQLite分页查询的三种方法- http://blog.csdn.net/lu1024188315/article/details/51734514
SQLite基本操作加数据库分页查询- http://blog.csdn.net/xfks55/article/details/6524792
Sqlite数据库分页查询(ListView分页显示数据)- http://www.tuicool.com/articles/FNnAnub
Android:SQLlite数据库操作最详细解析- http://www.jianshu.com/p/8e3f294e2828

-- SQL性能
提升SQL性能的8点整理和建议- http://blog.csdn.net/huangwenyi1010/article/details/70799810
sqlite 数据库性能调优- http://blog.csdn.net/bravegogo/article/details/53517610
微信 iOS SQLite 源码优化实践- https://www.qcloud.com/community/article/671906
IM中使用的是原生数据库SQLite。监听数据库变化的一个接口ContentObserver这个接口.

> SQLite原理, SQLite前端解析系统,SQLite后端引擎;创建索引,创建视图,创建触发器,drop命令.
sqlite的后端系统设计原理- http://www.kubiji.cn/juhe-id6724.html
SQLite剖析(5):体系结构- http://blog.csdn.net/zhoudaxia/article/details/8196838
sqlite 视图、触发器、索引和事务总结- http://blog.csdn.net/hustyangju/article/details/17488309

  首先我们来看 SQLite 的架构。SQLite 使用 B+树 存储一个表,整个 SQLite 数据库就是这些 B+树 组成的森林。对于每个表的元数据(表名、根节点地址、表 scheme 等),都记录在一个叫 sql_master 的表中。这个 sql_master 表(下简称 master 表) 本身也是一个 B+树 存储的普通表。
-- SQLite是一个适配不同平台的数据库,不仅支持多线程并发,还支持多进程并发。它的核心逻辑可以分为两部分:
  1. Core层。包括了接口层、编译器和虚拟机。通过接口传入SQL语句,由编译器编译SQL生成虚拟机的操作码opcode。而虚拟机是基于生成的操作码,控制Backend的行为。
  2. Backend层。由B-Tree、Pager、OS三部分组成,实现了数据库的存取数据的主要逻辑。
  SQLite算是非常稳定的数据库,不容易出现损坏,就算应用程序崩溃,或者操作系统崩溃,甚至是执行事务时出现断电,都能在下一次使用数据库时自动修复。但是,还是不能避免不出现损坏的情况。

-- SQLite由以下几个组件组成:SQL编译器、内核、后端以及附件。SQLite通过利用虚拟机和虚拟数据库引擎(VDBE),使调试、修改和扩展SQLite的内核变得更加方便。
 SQLite的存储后端是采用Btree实现,多个连接可以并发操作,但是同一时间只允许一个写着存在。
 sqlite是一个功能相对完整的数据库系统。

一个传统的数据库系统大体都可以划分成以下几部分:
1.connector pool(网络层,提供CS模式的数据库访问支持);
2.sql 解析&优化器;
3.数据管理&缓存;
4.存储引擎&虚拟机;
5.文件系统抽象层(OS层,屏蔽各种不同操作系统的API差异)。

 sqlite除了没有网络层的支持外,整体架构也基于以上的架构。整体上sqlite的功能系统被划分成两部分,即frontend(前端)和backend(后端)。前端实现sql的语法解析,生成sqlite虚拟机支持的中间代码;后端实现sqlite的文件结构、数据组织、存储缓存管理、VDBE虚拟机等功能。
 sqlite前端包括词法分析器、语法分析器与中间代码生成器三部分。
 sqlie内部用pager模块实现整个页管理功能。pager模块介于B+树和OS层之间,提供基于页的数据存储&缓存、锁管理以及日志管理功能。其中锁管理与日志管理结合实现了sqlite的事务支持,而页的存储缓存则提供了统一的读写服务,屏蔽上层调用对磁盘与内存的感知。
  sqlite的页在实际应用中被划分为leaf、internal、overflow及free四种类型的逻辑页。
 sqlite的Pager提供了对页一级的读写、锁、日志等操作。但是并没有实现任何数据库相关的概念(如表、索引、事务等)。
 sqlite的表是由B+树实现的。sqlite选用B–树来实现索引,这样索引占用的内存空间相对更少,容易加载到内存中。B–树和B+树都是多路平衡搜索树。
 sql的后端最上层就是sqlite的虚拟机VDBE(virtual database engine)[4]。VDBE是sqlite前端和后端的桥梁,sqlite的核心运行过程都是在VDBE中实现的。一个VDBE对象包括以下数据:
  1∙ 一个由sql解析器生成的字节码
  2∙ 查询column的名称和数据类型
  3∙ 输入参数值
  4∙ 程序计数器

> 微信开源 SQLite,WCDB(WeChat Database)组件
WCDB源码托管地址:https://github.com/Tencent/wcdb
WCDB开发者指南:https://github.com/Tencent/wcdb/wiki
微信正式开源移动端数据库组件WCDB- http://www.52im.net/article-240-1.html

-- 其他Demo
基于Google的LevelDB的键值数据库(NoSQL)A key-value database for Android- https://github.com/nhachicha/SnappyDB/
Android 通过反射让SQlite建表如此简单--http://blog.csdn.net/nugongahou110/article/details/46926345
SQLlite CRUD Demo- https://github.com/Carson-Ho/DataBase_Demo

> 加密SQLite (Android/iOS)  -- 主流的Sqlite数据加密技术就是sqlitecipher
SQLite官方下载最新版本- http://sqlcipher.net/ 
Android SQLite API based on SQLCipher- https://github.com/sqlcipher/android-database-sqlcipher
SQLCipher is an SQLite extension(256 bit AES)- https://github.com/sqlcipher/sqlcipher

为跨平台数据库引擎 SQLite 实现加密扩展- https://sites.google.com/site/notegainexp/sqlite/weikuapingtaishujukuyinqingsqliteshixianjiamikuozhan

IOS官方的地址-- http://sqlcipher.net/ios-tutorial/  
ios中的SQL数据库文件加密 (使用sqlcipher)- http://blog.csdn.net/kuai0705/article/details/8931996

-- SQLCipher和OpenSSL项目的框架代码都是开放的源代码:
OpenSSL库-- https://www.openssl.org/  http://www.openssl.org/source/(稳定版本)
sqlite加密-SQLCipher http://blog.csdn.net/zhaopenghhhhhh/article/details/37698405

> SQLite , SQL查询可以防止SQL注入?    
 下面这种是有注入问题的,查询语句是拼接的:
String conditions="orderno = '"+et_name.getText().toString()+"'";
List listOrderDetailsRead = (List)DataSupport.
where(conditions).
find(OrderDetails.class);    
 下面这种是安全的,将参数独立出来了:
List listOrderDetailsRead = (List)DataSupport.
where("orderno = ? ",et_name.getText().toString()).
find(OrderDetails.class);

> 数据库的crud,升级表/升级库,合并表/合并库,降级
开源库ORMLite或者GreenDao ActiveAndroid等。SQLite创建表与更新表与版本号的联系?

Android 数据库模块搭建方案- https://www.jianshu.com/p/57eb08fe071d
Android的Romm是Android官方整合出来的一揽子ORM数据库解决方案。
using Room instead of SQLite- https://developer.android.com/topic/libraries/architecture/adding-components.html
  Room在SQLite上提供了一个抽象层,以便在利用SQLite的全部功能的同时使流畅的数据库访问。
https://github.com/googlesamples/android-architecture-components/tree/master/PersistenceMigrationsSample

-- SQLite频繁读与写 , 打开与关闭
  Android中无法避免操作SQLite数据库,并且大家的一贯做法都是维系一个全局的单例句柄,保持SQLiteDatabase数据库句柄出于打开状态,避免多次打开耗时。SQLiteDatabase的读、写句柄,关闭连接句柄。SQLite实际是支持多线程(几乎)无锁地并发操作。
Android Sqlite常见异常:连接池关闭问题- https://zhuanlan.zhihu.com/p/27236021
android Sqlite多线程访问异常解决方案- https://www.cnblogs.com/wangmars/p/4530670.html
android之存储篇_SQLite数据库_让你彻底学会SQLite的使用- https://www.cnblogs.com/jingmo0319/p/5591234.html

-- SQLlite升级与降级
Android SQLite数据库版本升级原理解析- http://www.cnblogs.com/liqw/p/4264925.html
App版本更新时对SQLite数据库表的修改问题- http://blog.csdn.net/u013067184/article/details/48031081
Android SQLite数据库的数据升级与降级- http://www.cnblogs.com/zhaoyucong/p/6118226.html

-- 版本更新时,sqlite表结构发生变化了该怎样处理,最有效的方案就是先删除老的数据,重新调用onCreate(db);
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  context.deleteDatabase(DB_NAME);
  onCreate(db);

}

-- 升级与降级中的主要的三个方法:
  1.onCreate()该方法是在你没有安装过(第一次运行)的时候执行,这时可以在这个函数中完成初始的数据表的创建;调用时机是用户首次安装应用后启动,或是清除App数据库文件后启动。这时可以在这个函数中完成初始的数据表的创建。
  2.onUpgrade()该方法是在你安装过的情况下,对数据继续更新的时候执行,这时可以在这个函数完成数据库版本升级带来的旧版本的兼容问题,以及数据迁移问题;调用时机是用户在做应用更新,覆盖安装后启动,如果新版本中数据库版本号要比旧版本中的数据库版本号高则会调用。这时可以在这个函数完成数据库版本升级带来的旧版本的兼容问题,以及数据迁移问题。因为有的用户手机上本来就有第一版本的APP,所以在App升级到第二版本时会执行onUpgrade(),不会执行onCreate()。
  3.onDowngrade()该方法是在现逆向降级(如应用由版本号4降级安装版本号为3的包)时必须重写的方法,如果应用降级覆盖安装时没有重写该方法则会崩溃。

 - 数据库升级:增加表或增加字段,(删除表,删除字段)
SQLite数据库--升级数据库最佳操作- http://www.jianshu.com/p/4da13b38c1db
Sqlite数据库,增删改查,升级和事物- http://blog.csdn.net/ht1063899049/article/details/53643804
Android Sqlite 数据库版本更新- http://blog.csdn.net/long704480904/article/details/41325655

> 开源库GreenDao
项目搭建与增删改查操作- http://m.blog.csdn.net/article/details?id=51893092
GreenDao数据库框架的配置与增删改查- http://www.cnblogs.com/xiguameng/p/5950122.html
GreenDao(2)--使用- http://www.jianshu.com/p/3b07c1d833bb
利用greendao对SQLite数据库的操作- http://www.mamicode.com/info-detail-1474973.html
GreenDao3.2的使用- http://blog.csdn.net/Hi_AndG/article/details/54729433
greenDao分页加载- http://blog.csdn.net/haowei0708/article/details/51596837
第三方资源收集(GitHub)及SDK集成(GreenDao的升级和使用)- http://blog.csdn.net/shareus/article/details/52319945
GreenDAO3.0 带数据库升级 demo-- http://download.csdn.net/download/flybamboo/9660390
GreenDao生成数据库模型代码依赖jar- http://download.csdn.net/detail/fancylovejava/8859203
SQLite开源库GreenDao- https://github.com/greenrobot/greenDAO
升级数据库版本GreenDaoUpgradeHelper-https://github.com/yuweiguocn/GreenDaoUpgradeHelper
GreenDao集成及升级- http://blog.csdn.net/growth58/article/details/50453038
GreenDao集成及升级,greenDAo的增删改查,加上异常和异步的处理最好 同步和异步。GreenDao3.0先SDK版本升级,再GreenDao使用的数据库升级。GreenDao表升级(修改表结构;添加新表)
 -- greendao SDK升级 记录从greendao2.1升级到greendao3.2- http://blog.csdn.net/ghsy121/article/details/54924330
 -- GreenDao3.0 CRUD简单使用- http://www.jianshu.com/p/4986100eff90
GreenDao3.0 CRUD简单使用和升级- http://blog.csdn.net/u014695188/article/details/52913253
安卓 GreenDao 基本使用- http://blog.csdn.net/stimgo/article/details/56014486
greenDao3.0数据库基本使用及升级- http://download.csdn.net/download/zsp765098084/9716615
 -- GreenDao3.0的数据库升级(合并数据库旧的数据)- http://blog.csdn.net/liuchao9876543210/article/details/54582188
//app gradle
compile 'org.greenrobot:greendao:3.2.0'//add
//MyGreenDao gradle
compile 'org.greenrobot:greendao-generator:3.2.0'//add
//nayun_workplace gradle
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'//add
  Sqlite分页查询语句:select * from users order by id limit 10 offset 0 ,offset代表从第几条记录“之后“开始查询,limit表明查询多少条结果,分页查询 limit(int): 限制查询的数量; offset(int): 每次返回的数量;
/**
     * GreenDao中对SQLite的分页查询
     * 查询时默认是加了可重入锁,不用加synchronized
     *
     * @param page 需要查询的当前页
     * @return
     */
public List getDataWithPage(int page) {
        List ls = new ArrayList();
        ls = session.getCollectionDao().queryBuilder().offset((page - 1) * 10).limit(10).list();
        return ls;

    }

- ORM对象关系映射之使用GreenDAO进行CRUD操作- http://blog.csdn.net/u010687392/article/details/48444417
Android ORM 框架之 greenDAO 使用心得 http://www.open-open.com/lib/view/open1438065400878.html
GreenDAO数据库版本升级-http://blog.csdn.net/fancylovejava/article/details/46713445
数据库升级 http://blog.csdn.net/crystalddd/article/details/37742021
 db.execSQL(CREATE_TEMP_USER); //第一步将旧表改为临时表
 db.execSQL(CREATE_USER); //第二步创建新表(新添加的字段或去掉 的字段)
 db.execSQL(INSERT_DATA); //第三步将旧表中的原始数据保存到新表中以防遗失
 db.execSQL(DROP_USER); //第四步删除临时备份表

> SQLite使用过程中的问题集
1. SQLiteException: table TAREAS has no column;has no such DB
App版本更新时对SQLite数据库表的修改问题- http://blog.csdn.net/u013067184/article/details/48031081
SQLiteException: table TAREAS has no column - https://stackoverflow.com/questions/36308339/greendao-android-database-sqlite-sqliteexception-table-tareas-has-no-column-na , https://stackoverflow.com/questions/934237/sqlite-exception-no-such-table-error

2. SQLite数据库的库也可能会损坏?数据库损坏与修复
微信 SQLite 数据库修复实践- https://www.qcloud.com/community/article/764092
微信 SQLite 数据库修复实践- https://zhuanlan.zhihu.com/p/26697193
关于sqlite断电或者存储空间不足造成的数据文件损坏问题- http://blog.csdn.net/xp5xp6/article/details/50531364
  -- SQLite 损坏的原因:
1.文件错写;2.文件锁 bug;3.文件 sync 失败;4.设备损坏;5.内存覆盖;6.操作系统 bug;7.SQLite bug;
  -- 移动端数据库损坏的真正原因其实就3个:
1.空间不足;2.设备断电;3.文件 sync 失败(文件覆盖问题、文件锁问题、数据同步问题、内存问题)。
  -- SQLite使用建议:
1.减少多进程或多线程操作,尽可能单线程写。
2.减少事务操作,减小事务复杂度,减少检查点
3.减少数据库的大小
4.避免使用PRAGMA synchronous=OFF
5.断电不会由于SQLite写事务对数据库文件造成损坏,其实现机制就是利用了事务+日志机制,想具体了解就看hot journal或者Write-Ahead Log部分?
当磁盘空间写满或写入了格式不正确的数据或在操作db过程中内存溢出,那么.db文件的镜像就会被破坏,这种情况下再去执行有关此db的操作,android就会把该db文件删除掉,如果db文件损坏了,可在adb shell下恢复其数据,做法如下:
sqlite3 old.db(注:损坏的db文件)
.output tmp.sql;  .dump;  .quit;
然后读取数据到新的db
sqlite3 new.db;  .read tmp.sql;  .quit;

6. 不过保险起见还是做好db的备份,因为一旦db文件损坏,在未知的情况下再去操作此db,android就会直接把此db给干掉。

你可能感兴趣的:(数据库DB)