PREPARE(和预处理关联起来对比)
MySQL的SQL语句执行处理有两种方式即使SQL:一般情况下的statementSQL执行方式,
-
语法和语义解析
-
优化SQL指定执行计划
-
执行并返回结果
SQL走流程处理,一次编译,单次运行
-
预处理SQL:Prepare模式,当某需求某一条SQL语句可能会被反复调用执行时,或者每次执行的时候只有个别的值不同如:
-
select的where子句值不同
-
update的set子句值不同
-
insert的values值不同
-
-
如果每次都经过上述三个步骤执行那效率会很低,处于安全、效率引入预处理PREPAREstatement
所以预编译语句就是将此类SQL语句中的值用占用符替代,可以视为SQL语句模板化或者说参数化
总体可以理解为:一次编译,多次执行,省去了解析优化等过程;此外预编译语句能防止SQL注入
具体的Prepare模式的执行原理
通过JDBC接口连接数据库用prepare模式运行SQL语句的一个工具
由李强周编码实现了Prepare工具,底层使用JDBC接口连接数据库,通过prepare模式执行SQL语句,可以用作自动化测试
工具具体由JAVA语言编写,jar包如java_user.tar.gz,我本地有
Prepare工具的安装:
-
在虚机中创建用户java_user用户,adduser java_user
-
将软件包放入/home/java_user目录下
-
解压该软件包,安装包较大先上传好
Prepare工具的使用:
各个目录的大致作用:
-
bin:各种可执行的shell脚本,最常用的就是run.sh脚本
-
casefile:run.sh脚本后不加参数时的默认用例文件存放目录
-
changxml.sh: 不知道。。。
-
compare.out:执行完成后,结果文件和标准文件的对比结果存放文件
-
config:配置文件目录,常用的为config.properties文件
-
lib:用的各种组件库,包括自己写的prepare工具jar包
-
nohup.out:不知道没用过
-
preparesuite、test:自建目录,其中放用例文件,在run.sh加对应目录执行相应目录中的用例
-
symbak:之前的人备份的一些东西,应该可以删掉
-
symcase:系统测试用例,一些测试数据类型的用例,好像是MySQL官方的一些用例
-
standard:标准结果文件存放处,格式为x.xml_succ.out
-
result:执行完成后结果文件存放处,格式为x.xml.out
如何运行:
-
修改配置文件
-
connMode、totalPoolSize、initSize三个是与连接池相关的设置,连接池概念可以自己学习
-
driver:用到的核心方法,在prepare的ar包中,jar存放在lib目录中
-
url:jdbc接口url,后续参数若不了解流程千万不要修改,一般修改ip+port为想要执行语句的连接实例的ip+port即可
-
user、passwd:连接实例的账户和密码
-
目录信息:各个目录的作用上述描述过,一般情况下不要修改
-
threadCount:线程数,用例目录中存在多个用例时,会并发执行,但是否能达到设置线程数,需要资源足够
-
将需要执行的用例放在相应文件夹中
-
可以自建目录存放用例:如创建的test,preparesuite目录,将写好的xml文件放在其中,然后执行run.sh test或run.sh preparesuite
-
可以放在默认用例存放目录下:casefile,执行run.sh即执行casefile目录下的用例
-
结果、结果文件和标准结果文件
-
结果、结果文件和标准结果文件的概念与mysqlTest中的result、reject的概念类似
-
执行结果文件为:compare.out,其中会打印所有执行用例本次执行的结果和标准结果文件对比的结果,正常第一次执行其中应该全是fail
-
执行结果文件:将在DB中执行的结果打印入文件中,其中select会展现成列名=值的形式,如 a=1
-
标准结果文件:将已经稳定正确的结果文件修改文件名放入standard目录中,即为标准结果文件,注意文件名的一致性
Prepare用例的编写:
-
用例的格式为xml文件格式
-
最前面版本和编码不用修改
-
第二行group id不用修改,是否开启自动提交请根据实际情况填写
-
<sql id="" sql="" type=""></sql>或<sql id="" sql="" type=""/>
-
由<sql>包起来的内容为要执行的sql语句
-
id为当前sql语句的编号,不可重复,与后续<exe>会有联动
-
sql中即为要执行的语句
-
其中如果有像最开始所说的要变动的部分可以使用?作为占位符在该位置输入,同时要在同一<sql>语句内加上相应的<para>语句声明相应的数据类型,数据类型由数字代替,具体数字代指哪个格式最后会以附录方式放出
-
如果没有需要变动的位置,就正常输入语句
-
-
type为sql语句类型:
-
目前其中仅有三种参数:ddl、select、update
-
ddl语句类型与字面一致,前面sql中填写的是ddl类语句,后面type就写ddl
-
select类型代指读,基本上只有select 语句后面的type写select
-
update类型代指写,update、insert、delete、replace into、merge into等写语句都要写update类型
-
-
-
<exe id="" sqlId="" (value="" cycTimes="")/>
-
id为当前exe的编号,可以重复,当重复时会自动按上下顺序执行,最后的结果文件中的exe标数和用例里写的标数不一致是正常的,因为中间允许漏写,而结果文件只会统计从开始到结束执行了多少个exe与id无较大关系
-
sqlId为要执行的<sql>语句的id,与上述<sql>中的id对应,填写哪个就会执行哪个语句,多个exe填写相同的sqlId会按顺序执行多次该sql语句
-
value 选填项,当指定的sqlId中包含相应的占位符时,要填入相应的类型的数据
以三个‘?’占位符为例,填入格式为:
-
xx|xx|xx |,如10|1|999999.99996|即一个里面只填写一个数据,可以在里面填中文、英文和特殊字符,后一般不加cycTimes参数,如果加了也是生成同样的值
-
$SEQ(a,b)|$SEQ(c,d)|$SEQ(e,f)|,按顺序取数值,后一般加cycTimes循环次数,按顺序取值向占位符里填充
至于有没有其他方式,目前我还没用过,如果有人看懂代码看到其他替换占位符的方式或者用过其他替换占位符的方式也可以分享给大家
-
-
Prepare用例文件需要注意的几件事:
-
几个特殊符号在xml格式文件中需要替换下:
< < 小于号 > > 大于号 & & 和 ' ' 单引号 " " 双引号
-
数据类型:建议在编辑中查看
<!-- enum、set 类型归并到字符串11或12中,如果 dataType=" "或取值范围不在上述值中将默认以字符串类型传入 --> <!-- <dataType id="1" dbType="BIT" javaType="BOOLEAN" /> --> <!-- <dataType id="2" dbType="TINYINT" javaType="INTEGER" /> --> <!-- <dataType id="3" dbType="SMALLINT" javaType="INTEGER" /> --> <!-- <dataType id="4" dbType="MEDIUMINT" javaType="INTEGER" /> --> <!-- <dataType id="5" dbType="INTEGER" javaType="LONG" /> --> <!-- <dataType id="6" dbType="BIGINT" javaType="BIGINTEGER" /> --> <!-- <dataType id="7" dbType="FLOAT" javaType="FLOAT" /> --> <!-- <dataType id="8" dbType="DOUBLE" javaType="DOUBLE" /> --> <!-- <dataType id="9" dbType="DECIMAL" javaType="BIGDECIMAL" /> --> <!-- <dataType id="10" dbType="NUMERIC" javaType="BIGDECIMAL" /> --> <!-- <dataType id="11" dbType="CHAR" javaType="STRING" /> --> <!-- <dataType id="12" dbType="VARCHAR" javaType="STRING" /> --> <!-- <dataType id="13" dbType="TEXT" javaType="STRING" /> --> <!-- <dataType id="14" dbType="BOLB" javaType="BYTE" /> --> <!-- <dataType id="15" dbType="DATE" javaType="DATE" /> --> <!-- <dataType id="16" dbType="TIME" javaType="TIME" /> --> <!-- <dataType id="17" dbType="DATETIME" javaType="TIMESTAMP" /> --> <!-- <dataType id="18" dbType="TIMESTAMP" javaType="TIMESTAMP" /> --> <!-- <dataType id="19" dbType="YEAR" javaType="STRING" />--> <!-- <dataType id="20" dbType="BINARY" javaType="BYTE" />--> <!-- <dataType id="21" dbType="VARBINARY" javaType="BYTE" />-->
-
几个常见问题:
-
基本上前面两个填错了都会出现问题,而且报错很明显
-
查看执行结果时发现exe下没有打印出结果,但是sql语句在相应DB或者PROXY里执行没有问题,这是要考虑是否为“type”填错了