广告载入中...

SQL Server管理员不易养成的好习惯

发表时间:2010-05-28内容来源:站长资讯收集整理

一、开发初衷

相信大家在平时写SQL语句的时候,为了节省时间,都不太喜欢把小指放到Shift键上打出关键字的大写形式,比如建数据库,直接就create database...了,而不是CREATE DATABASE,反正SQL SERVER都可以执行语句,所以也就无所谓代码的效果了。

的确如此,但是编程都有规范一说,在SQL的编写中,将关键字大写就是一个规范,所以如果有这样的工具能够方便象我也是这样的懒人,批量将关键字替换成大写那就好了,不过饭来张口、衣来伸手可不是什么好习惯,所以还是DIY吧。。。

二、开发思路

建立Winform应用程序,依据需求此工具需要实现三个方面:

1、打开对话框——选择要处理的SQL文件路径;

2、保存对话框——选择处理完成后输出文件的路径;

3、核心功能——用正则表达式查找SQL文件中的关键字,如有匹配则将其转换为大写。

三、开发过程

俗话说:计划赶不上变化。本来计划一两个小时就能够搞定,但是还是足足折腾了一个下午,实在有些汗颜,下面就详细叙述一下过程吧:

1、搜集SQL关键字

要说SQL关键字,除了大家常见的CRUD相关的语句,还有FUNCTION、CURSOR、PROCEDURE、系统内置VARIABLE、VIEW、SCHEMA等等等等,总之一大堆,而且貌似也超出关键字的范畴了,要想完全搞定这么多东西,俺实在只能说无能为力了,所以我只搜集了大家平时经常用到的一些关键字,在下面的代码中会看到。

PS:当然如果园子里哪位能够做出一个覆盖所有SQL那样强大的来,小弟一定前往拜读。

2、SQL文件语句的遍历

不像ORACLE里的SQL PLUS那样难用的东西(主要是俺太菜了,经常出纰漏,很难一下就写对SQL),在SQL SERVER中SQL语句可以上下键随意更改内容或格式,而且语句也不用强制分号作为结尾,所以复杂的时候几行甚至十几行才是一个完整的SQL语句,所以一开始我就尝试从头到尾遍历整个文件貌似有些不太现实,最后的方案是采用了按行划分,以一行为一个数组进行处理,代码如下: 

  1. //先以行作为划分,得到一个数组  
  2.  Regex rowReg = new Regex("\r\n");  
  3.  string[] strRow = rowReg.Split("转换的SQL源文件内容"); 

3、现在依然不能急着处理strRow数组中的每一个元素,因为元素中有可能会出现"  create       database   "这样的情况,即关键字两侧有一个或多个空格字符,如果不进行统一处理,会给后面的替换带来很大的麻烦,所以这里再用一个正则表达式,使空格通通变成一个,随后再以空格作为分割符,这样才算得到了我们真正需要进行匹配替换操作的数组:

  1. for (int i = 0; i < strRow.Length; i++)  
  2.  {  
  3. strRow[i] = Regex.Replace(strRow[i], @"\s+"" ");  
  4. string[] strRowDetail = strRow[i].Split(new char['\0']);  

4、下面循环遍历strRowDetail数组中的每一项:

  1. for (int j = 0; j < strRowDetail.Length; j++)  
  2.  {  
  3.       if (regex.regRow.IsMatch(strRowDetail[j]))  
  4.       {  
  5.    Match match = regex.Match(strRowDetail[j]);  
  6.             ...  
  7.      }  
  8.  } 
 

为什么暂时省略了后面的代码呢,因为这样写考虑是不周全的,试想如果一个SQL语句如:

  1. create table student  
  2.  (  
  3.      cno varchar(50),  
  4.      ...  
  5.  ) 

这样关键字一个是一个的话,那匹配起来自然没有问题,但很多时候事情并没有那么简单,有些SQL语句包含了很多关键字。

最典型的就是日期类型的操作,比如:

  1. --求本月天数:select day(dateadd(mm,1,getdate())-day(getdate())); 
 

这样的一个SQL语句我们以空格划分后,那么数组的第二个元素会是day(dateadd(mm,1,getdate())-day(getdate())),如果进行上述的Match匹配就只会将第一个day变为大写,而其他则没有得到处理。

进行了一定的测试后,我转用了MatchCollection类,代码如下(注:tbSource指的是显示SQL代码的文本框):

  1. for (int j = 0; j < strRowDetail.Length; j++)  
  2. {  
  3.      //regex.regRow指的是寻找匹配关键字的正则表达式,在代码下载中会看到  
  4.    //首先查看strRowDetail[j]是否能够匹配  
  5.       if (regex.regRow.IsMatch(strRowDetail[j]))  
  6.      {   
  7.          //若能匹配则记录其匹配的内容   
  8.             MatchCollection mc = regex.regRow.Matches(strRowDetail[j]);   
  9.            //遍历匹配的集合  
  10.            for (int k = 0; k < mc.Count; k++)  
  11.         {  
  12.                //循环替换匹配的项  
  13. strRowDetail[j] = strRowDetail[j].Replace(               
  14. mc[k].Value, mc[k].Value.ToUpper());  
  15.            }  
  16.             //附加替换完成后的内容  
  17.              this.tbSource.Text += strRowDetail[j] + " ";  
  18.       }  
  19.        //不匹配则直接附加原来的内容  
  20.         else 
  21.        {  
  22.             this.tbSource.Text += strRowDetail[j] + " ";  
  23.        }  
  24.  }  
  25.   //因为最初是以行分割的,所以这里要附加\r\n,从而保持其原来的格式  
  26.   this.tbSource.Text += "\r\n"

5、最后用StreamWriter将得到的内容写入文件,这里除了编码问题貌似也没啥好说的了:

  1. StreamWriter writer = new StreamWriter(this.tbExportPath.Text, false
  2. Encoding.Default);  
  3. writer.WriteLine(this.tbSource.Text);  
  4. writer.Flush(); 

  • 站长资讯刊登此文只为传递信息,并不表示赞同或者反对作者观点。
  • 如果此内容给您造成了负面影响或者损失,本站不承担任何责任。
  • 如果内容涉及版权问题,请及时与我们取得联系。

文章评论

共有 位CH网友发表了评论 查看完整内容