简述

InstallShield已经内建了对MySQL和Oracle的支持。但是这个功能是通过ODBC实现的,它对SQL脚本的格式要求非常严格,因此已经通过官方客户端测试的脚本在IS中执行时往往就会报错。

一般来说,数据库脚本只保证通过官方客户端测试即可,同时维护一份供IS执行的脚本费时费力。因此,考虑安装程序对两数据库的支持通过官方客户端实现。

MySQL

 
function InstallMySQLComponent(szComponent)
NUMBER nResult;
STRING szServer,szDB,szUser,szPassword,sCMD,sOPT,sResult1,sResult2,svLine,sMsg,sPath;
NUMBER nvFileHandle,nvCount;
LIST listStatus;
begin
sMsg = '安装'+szComponent+' ...';
SdShowMsg(sMsg, TRUE);
// source命令不认识windows路径中的反斜杠,故将SRCDIR中的反斜杠替换成斜杠
sPath = SRCDIR;
StrReplace(sPath, '//', '/', );
// Fetch database connection information
SQLRTGetConnectionInfo( 'mysql', szServer, szDB, szUser, szPassword );
sCMD = WINSYSDIR^'cmd.exe';
sOPT = ' /c '+SRCDIR^'mysql.exe -h'+szServer+' -u'+szUser+' -p'+szPassword+' -D'+szDB;
sOPT = sOPT+' -e "source '+sPath^szComponent+'.sql" > '+SRCDIR^'dbstatus.txt 2>&1';
// Execute the script associated with the given component in database
nResult=LaunchAppAndWait(sCMD, sOPT, WAIT|LAAW_OPTION_HIDDEN);
if (nResult < ) then
MessageBox('Failed installing '+szComponent+' !', SEVERE);
abort;
endif;
// 关闭安装提示
SdShowMsg('', FALSE);
// Read dbstatus.txt
OpenFileMode(FILE_MODE_NORMAL);
if (OpenFile(nvFileHandle, SRCDIR, 'dbstatus.txt')<) then
MessageBox('Failed checking the status of installing '+szComponent+' !', SEVERE);
abort;
endif;
listStatus = ListCreate(STRINGLIST);
while GetLine(nvFileHandle, svLine) =
ListAddString(listStatus, svLine, AFTER);
endwhile;
CloseFile(nvFileHandle);
// Count how many lines fetched from dbstatus.txt
nvCount = ListCount(listStatus);
if nvCount > then
sMsg = "更新数据库出错,点“是”打开日志文件并退出安装,点“否”直接退出安装。/n";
sMsg = sMsg+"若错误可忽略,可选择数据库类型“none”以跳过数据库更新并直接更新程序,/n";
sMsg = sMsg+"然后在数据库中手工执行SQL脚本(安装后保存在script目录下)";
nResult = AskYesNo(sMsg, YES);
if (nResult = YES) then
LaunchApp(WINSYSDIR^'notepad.exe', SRCDIR^'dbstatus.txt');
endif;
abort;
endif;
end;

Oracle

 
function InstallOracleComponent(szComponent)
NUMBER nResult,nvFileHandle,nIndex,nvCount;
STRING sMsg,szServer,szDB,szUser,szPassword,sCMD,sOPT,sInstance,sTmp,svLine;
LIST listStatus;
begin
sMsg = '安装'+szComponent+' ...';
SdShowMsg(sMsg, TRUE);
// Fetch database connection information
SQLRTGetConnectionInfo( 'oracle', szServer, szDB, szUser, szPassword );
nIndex = StrFind(szServer, ':');
nIndex = StrFindEx(szServer, '/', nIndex);
StrSub(sInstance, szServer, nIndex+, );
sCMD = WINSYSDIR^'cmd.exe';
sOPT = ' /c '+'sqlplus.exe -L -S '+szUser+'/'+szPassword+'@'+sInstance;
sOPT = sOPT+' @'+SRCDIR^szComponent+'.sql > '+SRCDIR^'dbstatus.txt 2>&1';
// Execute the script associated with the given component in database
nResult=LaunchAppAndWait(sCMD, sOPT, WAIT|LAAW_OPTION_HIDDEN);
if (nResult < ) then
MessageBox('Failed installing '+szComponent+' !', SEVERE);
abort;
endif;
// 关闭安装提示
SdShowMsg('', FALSE);
// 在dbstatus.txt中查询字符串holytail,如果存在,说明脚本已执行完
if (FileGrep(SRCDIR^'dbstatus.txt', 'holytail', svLine, nIndex, RESTART) = ) then
// 在dbstatus.txt中查询字符串ORA-,如果存在,说明脚本执行出现错误
if (FileGrep(SRCDIR^'dbstatus.txt', 'ORA-', svLine, nIndex, RESTART) = ) then
sMsg = "更新数据库出错,点“是”打开日志文件并退出安装,点“否”直接退出安装。/n";
sMsg = sMsg+"若错误可忽略,可选择数据库类型“none”以跳过数据库更新并直接更新程序,/n";
sMsg = sMsg+"然后在数据库中手工执行SQL脚本(安装后保存在script目录下)";
nResult = AskYesNo(sMsg, YES);
if (nResult = YES) then
LaunchApp(WINSYSDIR^'notepad.exe', SRCDIR^'dbstatus.txt');
endif;
abort;
endif;
else
sMsg = "更新数据库出错,点“是”打开日志文件并退出安装,点“否”直接退出安装。/n";
sMsg = sMsg+"若错误可忽略,可选择数据库类型“none”以跳过数据库更新并直接更新程序,/n";
sMsg = sMsg+"然后在数据库中手工执行SQL脚本(安装后保存在script目录下)";
nResult = AskYesNo(sMsg, YES);
if (nResult = YES) then
LaunchApp(WINSYSDIR^'notepad.exe', SRCDIR^'dbstatus.txt');
endif;
abort;
endif;
end;

总结

  1. 为便于获取脚本在数据库中的执行结果,故通过官方客户端执行脚本时通过符号“>”将客户端的输出信息重定向到dbstatus.txt中;同时,使用“2>&1”将标准错误输出重定向到标准输出设备上,当然,会进一步重定向到dbstatus.txt文件中,否则,无法获取出错信息。
  2. sqlplus执行SQL脚本后不会自动退出,故应在Oracle的脚本后加上语句“exit;”。
  3. 重载OnSQLComponentInstalled()函数,并在其中禁止MySQL和Oracle的SQL脚本对应的Component被执行安装,然后通过以上两个函数更新数据库。

InstallShield在MySQL和Oracle中执行SQL脚本的方法InstallShield在MySQL和Oracle中执行SQL脚本的方法的更多相关文章

  1. Mybaits 源码解析 (七)----- Select 语句的执行过程分析(下篇)(Mapper方法是如何调用到XML中的SQL的?)全网最详细,没有之一

    我们上篇文章讲到了查询方法里面的doQuery方法,这里面就是调用JDBC的API了,其中的逻辑比较复杂,我们这边文章来讲,先看看我们上篇文章分析的地方 SimpleExecutor public & ...

  2. Oracle是如何工作的?实例是如何响应用户请求?一条SQL的执行过程~

    Oracle 是如何工作的? Select id,name from t order by id ; – SQL 解析(查看语法是否错误,如果没有错误,分析语意,执行此语句的权限) – 执行计划(OR ...

  3. SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变

    前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段 ...

  4. mysql中获取一天、一周、一月时间数据的各种sql语句写法

    今天抽时间整理了一篇mysql中与天.周.月有关的时间数据的sql语句的各种写法,部分是收集资料,全部手工整理,自己学习的同时,分享给大家,并首先默认创建一个表.插入2条数据,便于部分数据的测试,其中 ...

  5. PL/SQL中批量执行SQL脚本(不可把所有的语句都复制到New SQL Windows)

    PL/SQL中批量执行SQL脚本,不可把所有的语句都复制到New SQL Window,因为这样会导致缓冲区过大而进程卡死! 最好的办法是将要执行的SQL脚本存放到指定文件中,如C:\insert.s ...

  6. 如何将.SQL文件的数据导入到Mysql的数据库中

    一.用cmd的调试环境导入.sql文件中的数据: WinR键打开cmd输入: MySQL -u root -p 进入MySQL后MySQL>use DR;   MySQL> source  ...

  7. Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?

    Thinkphp中查询复杂sql查询表达式,如何表达MYSQL中的某字段不为空is not null?先上两种实现方式的实例:$querys["house_type_image"] ...

  8. oracle问题:新建了一个PDM文件,建表后生成的sql语句中含有clustered

    问题描述 为了在oracle中新增表,在PDM中建表,使用其生成的sql语句,但是建表不能成功,提示 ORA-00906: 缺失左括号 原因是多了clustered 关键字 情景重现 1. 新建一个p ...

  9. 【mybatis】service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据【事务的问题】

    问题描述: service层中一个方法中使用mybatis进行数据库的 多个修改操作,可能是update也可能是delete操作,但是sql语句命名执行并且在控制台打印出来了,但是数据库中未更新到数据 ...

随机推荐

  1. [HNOI 2013]切糕

    COGS 2398. [HNOI 2013]切糕 http://www.cogs.pro/cogs/problem/problem.php?pid=2398 ★★★☆   输入文件:nutcake.i ...

  2. 数据结构编程实验——chapter8-采用树结构的非线性表编程

    关于树结构的非线性表编程在数据结构中可以说占据了半壁江山,其中涉及的知识点繁杂,但也是数据结构体现运算优化的核心所在,下面我们将较为初步且系统得讨论数据结构中一系列有关树的表示. 首先我们再次明确树的 ...

  3. Docker容器加载宿主机的hosts解析

    前言 公司一直在用传统的tomcat下丢war包的架构体系,随着项目的增多.服务器数量的增多.需要为此花费很多时间在不同服务器的系统环境问题上.为了技术的与时俱进和工作的运维效率等方面,笔者引入doc ...

  4. 20155222 2016-2017-2 《Java程序设计》第7周学习总结

    20155222 2016-2017-2 <Java程序设计>第7周学习总结 教材学习内容总结 使用基于方法的语法在 Enumerable 类中调用 Where 方法时(像在 LINQ t ...

  5. Hadoop2.6.0在CentOS 7中的集群搭建

    我这边给出我的集群环境是由一台主节点master和三台从节点slave组成: master     192.168.1.2 slave1       192.168.1.3 slave2       ...

  6. JS比较两个数字大小

    js不能直降比较两·个数大小,要先转化为整数再比较大小. parseInt()转化. 出处:http://www.jb51.net/article/98251.htm

  7. getElementById()方法取值

    举例子: javascript: var time = document.getElementById('jidu').value; //指定时间 var taskclass = document.g ...

  8. C#反射-Assembly.Load、LoadFrom与LoadFile

    反射Demo: public class Person { public int Age; public void SayHello() { Console.WriteLine("Hello ...

  9. Chrome 清除某个特定网站下的缓存

    打开开发者工具(F12),选择 Network--Disable cache 即可.需要清除某网站缓存时 F12 打开开发者工具就会自动清除这个网站的缓存,而不必清除所有网站的缓存了.

  10. [转]坐在马桶上看算法:只有五行的Floyd最短路算法

    此算法由Robert W. Floyd(罗伯特·弗洛伊德)于1962年发表在“Communications of the ACM”上.同年Stephen Warshall(史蒂芬·沃舍尔)也独立发表了 ...