好一段时间没写博客了,这次我们来一起谈谈SQL文件执行器的功能实现,在ERP软件升级时往往在客户端程序更新的同时也要对数据库进行升级,ERP程序开发人员会对数据库升级的执行代码在开发的过程中以SQL文件的形式记录下来或者保存到特定格式的文件中供软件升级时使用,有些ERP软件会附带开发数据库升级工具来方便实施人员执行软件升级操作或者ERP软件内置数据库升级功能,不管使用什么样的方式能达到软件升级的目的就是好方法,这次我们就来剥离这部分的功能来实现一个SQL文件执行器,不特定于SQL文件,只要文件里面包含有SQL语法,而且能正常得到执行,在本执行器中就能正确的执行它(本次我们主要争对SQL文件,其他格式文件只要把相关控制去掉就好了,只是得不到很好的控制比较乱,或者你有更好的方法)。介绍性引入就到此为止了,接下来我们开始进入主题,研究一下SQL执行器的原理及设计思路吧。

一、SQL文件执行器原理分析

在分析原理之前,我们先来规范一下SQL文档的书写,我们在一个SQL语句结束的时候换行来个GO关键字再换行继续书写下一个SQL语句,遇到“USE [数据库名] ”语句时希望能把此语句单独放一行。做到以上书写规范我们开始原理分析:

1.上述SQL规范居然都做到了但是SQL文件里面的内容还不是我想要的,我想重新规范一下我的SQL文档,我想理想化它,所以我需要对SQL文件进行重新洗牌,我想我应该一行一行的阅读它,并把它提取出来去掉前后的空格,我应该重组改文件的内容并且在读取每一行的同时在其末尾写入一个换行回车符,而且我还想统计出每一个SQL文件中的SQL语句的个数(循环时会用到),我用GO关键字来标记了SQL语句的个数,在阅读到一行去掉首尾空格后只剩下不区分大小写的GO时我的统计会+1(统计从1开始),哦,这还永远不够,我还没考虑到USE关键字的处理,通常会选择一个数据库来执行相应的SQL文件,USE关键字在切换着数据库,我需要在检测到USE语句时切换数据库为USE后面跟着的数据库来执行后面的代码,所以我要把USE语句单独剥离开来以待做特殊的处理,往往我们写SQL文件的时候在USE语句的前后都不带GO关键字的,我需要给它加上。有一个需要注意的地方:USE [数据库名]  后面直接跟着SQL语句的(没有回车换行),这种写法在语法上是完全正确的,但是看上去就不是很美观了,这种方式我这边就不做处理了,请遵守上述规范吧,再处理下去程序性能就严重下降啦,本程序在数据库切换时是从USE 之后的字符开始到回车换行符结束来取数据库名的,这种写法会引发SQL异常。我需要构建一个这样的方法。

2.在第一点里面我们对SQL文件进行了格式化,现在开始我希望以GO关键字作为分割点,把SQL文件里面的SQL语法进行分段,我希望一段段的得到执行并返回执行结果,此时我需要一个循环来遍历文件中的SQL语句并执行它。本工具名字叫做SQL文件执行器很显然是争对批量SQL文件的处理的,所以一个循环是永远不够的,我还得在外面再套一个循环来遍历所有的SQL文件,对每个SQL文件进行分析并遍历其中的SQL语句执行它,这样就达到我们的目的了。貌似还有一个问题未处理,比如在执行到一半的时候我不执行了需要强制停止他这如何是好呢,强制关闭程序很显然是不可取的很容易引发未知的数据库异常或者造成数据丢失这些状况都是我们不想看到的,那么有什么好办法呢?此时我启用了臭名远扬的goto语句来从深层嵌套循环中跳出循环,我让他在用户发出停止指令后在执行完当前的SQL语法段后跳出循环,从而停止接下来的SQL语法的执行,这样子保障了SQL数据的安全,在SQL文件执行的期间,程序是不允许关闭的,除非向程序发出停止指令,并成功停止的时候,才允许程序关闭。

很简单的一个程序,我就大致的做以上两点的原理分析吧,接下来我上传下我的程序界面设计图吧,大家参考下:

接下来我贴上来一些主要源代码供参考,代码可能看上去有些难懂,表述性不是很好,期待大家来改进它:

这是对SQL文件中的语法进行重新洗牌的方法

        /// <summary>
/// 读取文件内容(SQL关键字特殊处理主要针对GO关键字)
/// </summary>
/// <param name="path">文件路径</param>
/// <param name="keywords">关键字</param>
/// <param name="str">输出字符串</param>
/// <param name="i">keywords的个数</param>
public void FileReader(string path,string keywords,out int i,out string str)
{
bool useplusgo = false;//use后面是否跟着go
bool goplususe = false;//use前面是否存在go
StreamReader sr = new StreamReader(path, Encoding.GetEncoding("GB2312"));
//str = sr.ReadToEnd();
string s = null;
string temp = null;
int x = 0;
while ((temp = sr.ReadLine()) != null)
{
if (temp.Trim().ToUpper() == keywords.ToUpper())
{
useplusgo = false;//use语句后面跟着go则关闭use判断
goplususe = true;//use前面存在go
x++;
s += "\r\n" + keywords + "\r\n \r\n";
}
else if (temp.Trim().Length >= 4 && temp.Trim().ToUpper().Substring(0, 4).Trim() == "USE")
{
temp = temp.Trim().Replace("[", "").Replace("]", "");
//如果use前面不存在go则加上
if (!goplususe && s != "\r\n" && s != null)
{
x++;
s += "\r\n" + keywords + "\r\n\r\n" + temp + "\r\n";
}
else
{
s += temp + "\r\n";
}
useplusgo = true;
}
else
{
goplususe = false;//go后面不跟use关闭判断
//如果use后面不跟go则加上go
if (useplusgo)
{
x++;
s += "\r\n" + keywords + "\r\n" + temp + "\r\n";
useplusgo = false;//关闭use判断
}
else
{
s += temp + "\r\n";
}
}
}
i = x;
str = s;
sr.Close();//关闭当前打开的文件
}

这个是处理USE语句的方法

        /// <summary>
/// 获取use后面的数据库名称
/// </summary>
/// <param name="str">use字符串行</param>
/// <returns></returns>
public string UseStatementProcessing(string str)
{
string[] strSplit = Regex.Split(str, "\r\n", RegexOptions.IgnoreCase);
int x = strSplit.Length;
string s = "";
if (/*strSplit[0].ToUpper().IndexOf("USE ", 0) >= 0*/Regex.IsMatch(strSplit[0].ToUpper(), "USE ", RegexOptions.IgnoreCase))
{
s = strSplit[0].Substring(4, strSplit[0].Length - 4).Trim();
}
else if (/*strSplit[1].ToUpper().IndexOf("USE ", 0) >= 0*/Regex.IsMatch(strSplit[1].ToUpper(), "USE ", RegexOptions.IgnoreCase))
{
s = strSplit[1].Substring(4, strSplit[1].Length - 4).Trim();
}
else
{
s = "";
}
return s;
}

这次话题就到此为止吧,这程序比较简单,大家可以写写玩,当作练练手也不错,主要在于文件的操作和字符串的处理。

C# SQL文件执行器的功能实现的更多相关文章

  1. SQL脚本文件执行器

    处于项目需求,需要能够批量执行SQL脚本文件,需要由前台页面操作触发执行. 查找相关资料,发现 Ant 提供了 SQLExec 组件可以支持SQL文件的执行,测试效果不错. 以下是对 SQLExec ...

  2. mysql 导入导出.sql文件

    备份数据库(包含全部表和全部存储过程):C:\Documents and Settings\Administrator>mysqldump -h localhost -u root -p -R ...

  3. 批量执行SQL文件

    原文:批量执行SQL文件 摘要:很多时候我们在做系统升级时需要将大量的.sql文件挨个执行,十分不方便.而且考虑到执行顺序和客服的操作方便性,能不能找到一种简单的方法来批量执行这些sql文件呢? 主要 ...

  4. SQL点滴7—使用SQL Server的attach功能出现错误及解决方法

    原文:SQL点滴7-使用SQL Server的attach功能出现错误及解决方法 今天用SQL Server 2008的attach功能附加一个数据库,出了点问题,提示的错误是: Unable to ...

  5. java 网络编程之TCP通信和简单的文件上传功能

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  6. navicat导入.sql文件

    用Navicat for Mysql导入.sql文件   虽然这算不上什么难事,但是对于新手来说(比如说我),Navicat for MySQL里的导出连接.运行SQL文件.导入向导.还原备份.这些功 ...

  7. oracle导入大sql文件

    最近遇到一个需要导入大SQL文件的问题,最先直接用SQL developer 导入大SQL文件,结果报IO Exception,只好采用sqlplus 导入,操作过程如下: sqlplus 用户名/密 ...

  8. [.NET开发] C#实现的SQL备份与还原功能示例

    本文实例讲述了C#实现的SQL备份与还原功能.分享给大家供大家参考,具体如下: //记得加 folderBrowserDialog1 openFileDialog1 控件 using System.D ...

  9. PHP导出sql文件

    发现自己之前写的php导出sql数据为Excel文件在导出一些数据的时候出现了精度的问题,比如导出身份证号的时候会把后面变成0000.暂时先把这个问题留下,有空去看看到底是什么问题. 写了一个导出sq ...

随机推荐

  1. c++ string.find()函数的陷阱

    string.find(char *)查找字符串中是否包含子串 找到:返回第一个索引 没有找到:返回一个很大的随机数字而不是返回负数(这是个坑) 所以不能这么写if (string.find(str) ...

  2. javascript第九课"闭包"

    所谓闭包:就是一个函数内部又定义了一个函数,而这个函数能访问外部函数作用域范围内的变量,这个内部函数就叫做闭包!   js中的面向对象都是使用闭包来实现的 闭包里使用的变量会现在当前函数内搜索,没有的 ...

  3. use magento default datepicker plugin in your project

    <action method="addItem"><type>js_css</type><name>calendar/calenda ...

  4. HBASE学习笔记--概述

    定义: HBase是一个分布式的.面向列的开源数据库,HBase是Google Bigtable的开源实现,它利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理H ...

  5. Object的增。删。查。改。遍历

    1.增: 1.向对象添加属性和方法 (私有) --->   obj.属性 ="";  2.向对象原型添加方法 (公共) --->      obj.prototype. ...

  6. EC读书笔记系列之10:条款16、17

    条款18 让接口容易被正确使用,不易被误用 记住: ★“促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容 ★“阻止误用”的办法包括建立新类型.限制类型上的操作,束缚对象值,以及消除客户的 ...

  7. EC读书笔记系列之9:条款16、17

    条款16 成对使用new和delete时要采取相同形式 记住: ★若你在new表达式中使用[ ],必须在相应的delete中也使用[ ],反之亦然 -------------------------- ...

  8. leetcode Count and Say python

    class Solution(object): def countAndSay(self, n): """ :type n: int :rtype: str " ...

  9. php 接收curl json 数据

    curl -H "Content-Type: application/json" http://127.0.0.1:8000 -X POST -d 'xxxx' php $strP ...

  10. mysql开启慢查询方法

    1,配置开启 Linux: 在mysql配置文件my.cnf中增加 log-slow-queries=/var/lib/mysql/slowquery.log (指定日志文件存放位置,可以为空,系统会 ...