文章描述:主要说明转换成SQL语句的过程。----必要信息(数据库名,表名,条件)转换成SQL语句

一些界面上数据增删改查的操作往往只需要输入一数据库名,表名,加条件就可以进行数据查询了,在这背后是怎么实现了呢,这些程序有些是使用封装的方法,有些直接输入sql语句进行操作,封装的方法最后也是将查询条件(上面输入操作)转换为SQL语句用Statement对象对应方法进行相关操作

JAVA:

而Statement对象获得SQL语句后怎么执行查询(这个不归statement管了),Statement这里是通过jdbc(或者其他驱动如:ODBC等)将SQL语句放入数据库,由数据库进行解释操作。这个速度较慢

preparedstatement:是java这边将原始的SQL语句进行解释,然后将中间码录入数据库,数据库直接执行,这样速度相比statement这种方式会更快!!!

Android:

首先通过Statement对象执行sql语句,最后获得PreparedStatement对象即指向底层对象的指针,调用底层方法执行sql语句。

个人认为android的数据库操作都是直接或间接使用PreparedStatement对象执行(底层源码我确实没有看过)

我是一条分割线^_^


在android中,提供了一些方便数据操作方法,不需要程序员写sql语句,只需要写如关键参数+条件。后面执行过程不需要我们考虑。

如android中的SQLite操作SQLiteDatabase封装很多方法

insert(String table, String nullColumnHack, ContentValues initialValues )//Convenience method for inserting a row into the database.

简单的方法对于插入一行数据到数据库中

@param table:表名

@param nullColumnHack:要强行插入null值的列名

@param initialValues :是一个HashMap存储的键值对,里面的key代表columnName列名,value代表在该行的key值所对应列要插入的值

一般情况下nullColumnHack为null

ContentValues contentValues = new ContentValues();
String name="我是书的名字";
contentValues.put("bookName",name);
insert("book",null,contentvalues)

上面insert语句最后会转化为SQL语句

insert into book(bookName) values("我是书的名字")数据往往都是在用户在输入界面提供,把这些内容组拼到insert语句当用户输入的内容含有单引号时,组拼出来的SQL语句就会存在语法错误。要解决这个问题需要对单引号进行转义,也就是把单引号转换成两个单引号。有些时候用户往往还会输入像“ & ”这些特殊SQL符号,为保证组拼好的SQL语句语法正确,必须对SQL语句中的这些特殊SQL符号都进行转义,显然,对每条SQL语句都做这样的处理工作是比较烦琐的。

所以通过使用占位符参数(?)

insert into book(bookName) values(?) 可以避免处理上面复杂问题

转换过程如下。

StringBuilder sql = new StringBuilder();//StringBuilder一个可变的字符序列
sql.append("INSERT");
sql.append(CONFLICT_VALUES[conflictAlgorithm]);
sql.append(" INTO ");
sql.append(table);
sql.append('(');
Object[] bindArgs = null;//bindArgs存放的是value[]数组,要插入的数据
int size = (initialValues != null && initialValues.size() > 0)
? initialValues.size() : 0;
if (size > 0) {
bindArgs = new Object[size];
int i = 0;
for (String colName : initialValues.keySet()) {//循环添加列名对应insert into table(colName1,..2,...colN)括号里面的所有列名
sql.append((i > 0) ? "," : "");
sql.append(colName);
bindArgs[i++] = initialValues.get(colName);//将要插入的数据全部复制到bindArgs数组中
}
sql.append(')');
sql.append(" VALUES (");
for (i = 0; i < size; i++) {
sql.append((i > 0) ? ",?" : "?");
}
} else {
sql.append(nullColumnHack + ") VALUES (NULL");
}
sql.append(')');

上面形成sql语句是insert into book(bookName) values(?),还有生成一个数据数组bindArgs。这是简单sql语句,这里还包含有处理约束过程

如 insert [or CONFLICT] into book(bookName) values(?)这个CONFLICT的约束冲突有5种ROLLBACK | ABORT | FAIL | IGNORE | REPLACE

private static final String[] CONFLICT_VALUES = new String[]
{"", " OR ROLLBACK ", " OR ABORT ", " OR FAIL ", " OR IGNORE ", " OR REPLACE "};

ON CONFLICT子句不是独立的SQL命令。这是一条可以出现在许多其他SQL命令中的非标准的子句。由于它并不是标准的SQL语言,这里单独介绍它。

ON CONFLICT子句的语法在如上的CREATE TABLE命令中示出。对于INSERT和UPDATE,关键词“ON CONFLICT”由“OR”替代,这样语法显得自然。例如,不用写“INSERT ON CONFLICT IGNORE”而是“INSERT OR IGNORE”。二者表示相同的意思。

INSERT或UPDATE的OR子句定义的算法会覆盖CREATE TABLE所定义的。ABORT算法将在没有定义任何算法时缺省使用。

ROLLBACK

当发生约束冲突,立即ROLLBACK,即结束当前事务处理,命令中止并返回SQLITE_CONSTRAINT代码。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。

ABORT

当发生约束冲突,命令收回已经引起的改变并中止返回SQLITE_CONSTRAINT。但由于不执行ROLLBACK,所以前面的命令产生的改变将予以保留。缺省采用这一行为。

FAIL

当发生约束冲突,命令中止返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留。例如,若一条UPDATE语句在100行遇到冲突100th,前99行的改变将被保留,而对100行或以后的改变将不会发生。

IGNORE

当发生约束冲突,发生冲突的行将不会被插入或改变。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。

REPLACE

当发生UNIQUE约束冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法。

当冲突应对策略为满足约束而删除行时,它不会调用删除触发器。但在新版中这一特性可能被改变。

如果数据initialValues 的值为null,则会执行insert into book(nullColumnHack) values(NULL)强行将列的值设为null

----到最后,会将statement对象和bindArgs数据进行绑定最后给数据库解释执行

感觉其它封装的数据库类原理和这个都是相似的吧

总结:

执行数据库操作的步奏:

  1构造Statement对象

2statement来执行某种(增删改查etc.)操作

3通过session调用到连接池中某个connection的execute相关方法。

4在connection中重新构建PreparedStatement(其实该对象才真正指向sqlite中的stmt),绑定数据和PreparedStament对象,调用Native方法底层JNI

PS:

android中sqlite的内部流程

打开数据库操作Android SQLite 打开、操作分析

SQLiteDatabase.openDataBase
SQLiteDatabase.open
SQLiteDatabase.openInner
SQLiteConnectionPool.open
SQLiteConnectionPool.openConnectionLocked打开连接池
SQLiteConnection.open
nativeOpen最后调用底层打开

执行数据库操作

SQLiteStatement statement = new SQLiteStatement()时,使得该SQLiteDatabase的某个connection拥有对应的PreparedStatement.

statement.execute()时,会在SQLiteDatabase的多个connection中找到含有对应PreparedStatement的connection来使用.

假如该connection恰巧被其他线程使用了,得到的是另一个connection,其会重新acquirePreparedStatement。

DatabaseUtils.getSqlStatementType(mSql)这个mSql语句为select

db.getThreadSession().prepare//SQLiteSeesion
SQLiteConnection.prepare
SQLiteConnection.acquirePreparedStatement(sql)
----SQLiteConnection中操作
statement=SQLiteConnection.mPreparedStatementCache.get(sql)
if(statement!=null)
{
if (!statement.mInUse) { // 并且不在使用中
return statement; // 返回该statement
}
skipCache = true; // 如果已在使用 另备一份并不再缓存
}
final int statementPtr = nativePrepareStatement(mConnectionPtr, sql); //native
try {
final int numParameters = nativeGetParameterCount(mConnectionPtr, statementPtr);
final int type = DatabaseUtils.getSqlStatementType(sql);
final boolean readOnly = nativeIsReadOnly(mConnectionPtr, statementPtr);
statement = obtainPreparedStatement(sql, statementPtr, numParameters, type, readOnly); // 从池中获取一个statement,并将其从池中移除
if (!skipCache && isCacheable(type)) {
mPreparedStatementCache.put(sql, statement); // 将statement放入缓存中
statement.mInCache = true;
}
statement.mInUse = true;
return statement;
------获得PreparedStatement

SQLiteOpenHelper保证一个实例里只有一个SQLiteDatabase

SQLiteDatabase.openDatabase的过程是构建SQLiteDatabase对象的过程,实质是构建SQLiteDatabase的成员变量SQLiteConnectionPool的过程,该过程是一个获取primaryConnection的过程。

每个线程有自己的SQLiteSession且只有一个,每个SQLiteSession在某一时刻最多只有一个SQLiteConnection(需要时从连接池获取,用完返还),保证了一个线程在某一时刻只有一个SQLiteConnection连接到某一SQLiteDatabase。事务同样通过Session来实现,故线程之间的事务是独立的

SQLiteConnectionPool掌管某个SQLiteDatabase的连接池。确保PrimaryConnection只有一个,如果空闲则将其返回,如果正被其他session使用则返回空,如果没有则新建。对于非PrimaryConnection,将会在连接池中优先选取stmt相同的,如果没有相同的获取池中最后一个,如果池子已经空了(此时多个线程同时用着多个连接),新建一个非主连接。

不知道有没有错,先记着两片不同文章,

Android SQLite 打开、操作分析

Android sqlite数据库连接池连接异常分析

 

数据库-转换sql语句的更多相关文章

  1. 在线数据库表(sql语句)生成java实体类工具

    相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设 ...

  2. Oracle,SQL Server 数据库较MySql数据库,Sql语句差异

    原文:Oracle,SQL Server 数据库较MySql数据库,Sql语句差异 Oracle,SQL Server 数据库较MySql数据库,Sql语句差异 1.关系型数据库 百度百科 关系数据库 ...

  3. 总结一些关于操作数据库是sql语句还是存储过程问题

    总结一些关于操作数据库是sql语句还是存储过程问题 程序中,你跟数据的交互,需要向数据库拿数据.更改数据库的数据等,这些操作,本身不是程序完成的,而是程序发命令给数据库去做的,不管是通过sql语句方式 ...

  4. SQL Server 【附】创建"商品管理数据库"、"学生选课数据库"的SQL语句

    附:(创建“商品管理数据库”的SQL语句) --建立"商品管理数据库"数据库-- create database 商品管理数据库 on(name='商品管理数据库_m', file ...

  5. GP数据库 常用SQL语句

    GP数据库 常用SQL语句 --1,查看列名以及类型 select upper(column_name) ,data_type from information_schema.columns wher ...

  6. Oracle数据库 基础SQL语句练习

    一.说明 第一次使用Oracle,想做一些练习,熟悉一些oracle. 表:使用的是scott用户,默认的表 具体表讲解,可以参考该文档:https://www.cnblogs.com/xjcheng ...

  7. mysql(数据库,sql语句,普通查询)

    第1章 数据库 1.1 数据库概述 l 什么是数据库 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作. l 什 ...

  8. [数据库]简单SQL语句总结

    1.在查询结果中显示列名:a.用as关键字:select name as '姓名'   from students order by ageb.直接表示:select name '姓名'   from ...

  9. 《大话数据库》-SQL语句执行时,底层究竟做了什么小动作?

    <大话数据库>-SQL语句执行时,底层究竟做了什么小动作? 前言 大家好,我是Taoye,试图用玩世不恭过的态度对待生活的Coder. 现如今我们已然进入了大数据时代,无论是业内还是业外的 ...

随机推荐

  1. HDU1518 Square(DFS) 2016-07-24 15:08 49人阅读 评论(0) 收藏

    Square Problem Description Given a set of sticks of various lengths, is it possible to join them end ...

  2. PBOCIC读芯片卡流程

    https://blog.csdn.net/kxd_ysheng/article/details/21178101?_t=t PBOCIC读芯片卡流程,参考上面的博客,整理了一下PBOCIC卡读流程. ...

  3. TCP/IP模型的一个简单解释

    TCP/IP模型是互联网的基础. 想要理解互联网,就必须理解这个模型.但是,它不好懂,我就从来没有搞懂过. 前几天,BetterExplained上有一篇文章,很通俗地解释了这个模型.我读后有一种恍然 ...

  4. Spring MVC 的@RequestParam注解和request.getParameter("XXX")

    在SpringMVC后台控制层获取参数的方式主要有两种,一种是request.getParameter("name"),另外一种是用注解@RequestParam直接获取.这里主要 ...

  5. maven 学习:为什么要使用maven,maven使用过程中的一些参数

    Maven是一个基于Java平台的项目构建工具. 设计的出发点: 在进行软件开发的过程中,无论什么项目,采用何种技术,使用何种编程语言,我们要重复相同的开发步骤:编码,编译,测试,生成文档,打包发布. ...

  6. Americans are usually tolerant (Listen speak of Unit 2)

    Americans are usually 1) tolerant of non-native speakers who have some 2) trouble understanding Engl ...

  7. 删除map、list集合元素总结

    @Testpublic void removeElementFromMap(){Map<Integer, String> test = new HashMap<Integer, St ...

  8. IIS 绑定 HTTPS 域名

    HTTPS为SSL安全通道,虽然并不清楚具体有什么用,但至少网站看上去比HTTP上档次,访问速度也没什么影响,所以有条件的话,还是做下,可以做噱头忽悠人. WIN2008系统 因为端口443冲突,只能 ...

  9. echarts呈现数据表图形

    讲一下echarts的用法,列举了两个图表,一个是单柱图,一个是多柱图,至于饼状图,只许更改echarts的类型就好了 一.首先是要两个div,用来存放两个图表 <div class=" ...

  10. C# 对接Https接口

    最近公司项目需要对接Https接口,将对接的代码整理如下: public void Get() { HttpWebRequest request = null; request = WebReques ...