DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: 19137911446
今日帖子: 17
在线用户: 10
导航: 论坛 -> 数据库专区 斑竹:liumazi,waterstone  
作者:
男 aknightchen (.) ★☆☆☆☆ -
盒子活跃会员
2023/9/24 22:49:27
标题:
分享一个函数:  去除SQL语句中的注释(支持行注释和区域注释) 浏览:593
加入我的收藏
楼主: function fDelSQLComment(sText:string):string;
var
  i,iQuotCount,iLen,iAreaCommentCount:Integer;
  bLineComment,bAreaComment:Boolean;
const
  TMP_REPLACE_STR=#9+#11+#6+#4;
begin

  //////////
  //
  //        函数说明:
  //
  //        由于ClientDataSet+DataSnap,在执行SQL时, 如果内含注释,在部分机上,可能会引起异常.
  //        (异常表现在: 能查询数据, 但查出数据记录为0)
  //
  //        所以, 我就搞了这个小函数. 用于去除SQL中注释
  //        可以处理:
  //        1>.  能正确识别单引号, 区分并删除"--"后面的"行"注释.
  //        2>.  能删除 /*.....*/之间的注释
  //        3>.  还能删除 /*..../*....*/....*/这样的欠套注释
  //          (SQL查询分析器就支持这次注释,所以,我也要符合它!)
  //
  //          如有改进, 欢迎mail给我: 1686616300@qq.com
  //////////


  Result:='';

  //统一换行符为#13
  sText:=AnsiReplaceText(sText,#13+#10,TMP_REPLACE_STR);
  sText:=AnsiReplaceText(sText,#13,TMP_REPLACE_STR);
  sText:=AnsiReplaceText(sText,#10,TMP_REPLACE_STR);
  sText:=AnsiReplaceText(sText,TMP_REPLACE_STR,#13);

  iQuotCount:=0;

  bLineComment:=False;
  bAreaComment    :=False;

  // 每遇到一个 "/*",就加1, 遇到 "*/",就减1, 以便符合SQL查询分析器的算法
  //SQL查询分析器中,   如果:  /****/****/***/ 像这样,有两对"/* */"包含的, 它是取最外层有效!
  iAreaCommentCount:=0;

  iLen:=Length(sText);


  for i:=1 to iLen do
  begin
    if (not bAreaComment) and (not bLineComment) and (sText[i]=Char(39)) then
    begin
      //单引号计数
      Inc(iQuotCount);
    end;

    if ((iQuotCount mod 2)=1) then
    begin
      //引号内的数据

    end
    else
    begin
      //引号,以及引号外的
      if bAreaComment then
      begin
        //属于"/*"后面的内容

        if (i>=2) and (sText[i-1]='*') and (sText[i]='/') then
        begin
          Dec(iAreaCommentCount);

          if iAreaCommentCount=0 then
          begin
          bAreaComment:=False; //区域注释结束
          end;
        end
        else if (i<iLen) and (sText[i]='/') and (sText[i+1]='*') then
        begin
          //在注释中, 又再次遇到了 "/*", 这里就要注意, 要和SQL查询分析器一样的算法
          Inc(iAreaCommentCount);
        end;

        Continue;   //  区域注释结束符"*/"不用处理,Continue
      end
      else if bLineComment then
      begin
        //属于"--"后面的内容

        if (sText[i]=#13) then
        begin
          bLineComment:=False; //换行符了.(当然,这个换行符,也一样要加进去
        end
        else
        begin
          //"--"后面的数据,(仍是同一行),可以隐掉
          Continue;
        end;
      end
      else
      begin
        //还没有"--"
        bLineComment:=(sText[i]='-') and (i<iLen) and (sText[i+1]='-');
        if bLineComment then Continue; //是"--"开始,那我们就直接忽略这个字符了

        bAreaComment:=(sText[i]='/') and (i<iLen) and (sText[i+1]='*');
        if bAreaComment then
        begin
          // 每遇到一个 "/*",就加1, 遇到 "*/",就减1, 以便符合SQL查询分析器的算法
          iAreaCommentCount:=1;
          Continue; //是"/*"开始,那我们就直接忽略这个字符了
        end;
      end;

    end;

    Result:=Result+sText[i];
  end;

  //最后,再把换行符替换成#13#10
  Result:=AnsiReplaceText(Result,#13,#13+#10);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo2.Text:=fDelSQLComment(Memo1.Text);
end;

----------
以下是测试例子(经函数处理后, 能和SQL查询分析器一样的解释):

declare @a nvarchar(10)
set @a=''
declare @b nvarchar(10)
set @b=''

SELECT 1 --AAAAA
SET @A=@a+'--1' --AAAA 
SET @A=@a+'2--'+''''+'--3' /*
/**********/
/***--*/'''
SET @A=@a+'4/*'--
SET @a=@a+'--5****/' */

select @a
----------------------------------------------
...
作者:
男 aknightchen (.) ★☆☆☆☆ -
盒子活跃会员
2023/9/24 22:51:43
1楼: 使用到 StrUtils 标准单元的函数: AnsiReplaceText
----------------------------------------------
...
作者:
男 tuesdays (Tuesday) ▲▲▲▲△ -
普通会员
2023/9/25 9:15:43
2楼: 我记得sql是自己过滤注释的啊. 
不需要自己手工干预.
此帖子包含附件:
PNG 图像
大小:13.4K
----------------------------------------------
delphi界写python最强, python界写delphi最强. 写自己的代码, 让别人去运行.
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行367.1875毫秒 RSS