iBATIS中替换“IN”的方法

IN的危害

  1. 由于in不支持变量绑定。所以,in语句必须使用“$变量$”来描述,为sql注入埋下了隐患。
  2. 同样,sql语句解析和执行计划不能复用。
  3. 由于执行计划不能复用,当发生很多次IN不同内容调用的时候,会把以前的经常复用的sql语句的执行计划cache给挤出去。

如何消灭IN

  1. 把in变成参数。
  2. 固定参数的长度。

步骤

  1. 创建函数 SplitInt.sqlSplitStr.sql  效果如下:

     
    select * from SplitInt(1,2,3,4,5,6);

    select * from SplitStr('a,b,c,d,e,6');

    ---------------------
    SplitInt.sql:
    CREATE FUNCTION [dbo].[SplitInt]
    (
     @SplitString varchar(8000)
    )
    RETURNS @SplitIntTable TABLE
    (
     [value] int
    )
    AS
    BEGIN
        DECLARE @Separator varchar(2);
        DECLARE @CurrentIndex int;
        DECLARE @NextIndex int;
        DECLARE @ReturnText int;
        SELECT @CurrentIndex=1;
        SELECT @Separator = ',';
        WHILE(@CurrentIndex<=len(@SplitString))
        BEGIN
            SELECT @NextIndex=charindex(@Separator,@SplitString,@CurrentIndex);
            IF(@NextIndex=0 OR @NextIndex IS NULL)
                SELECT @NextIndex=len(@SplitString)+1;
           
            SELECT @ReturnText=cast(substring(@SplitString,@CurrentIndex,@NextIndex-@CurrentIndex) as int);
            INSERT INTO @SplitIntTable([value])
            VALUES(@ReturnText);
           
            SELECT @CurrentIndex=@NextIndex+1;
        END
        RETURN;
    END
    --------------------------------
    SplitStr.sql:
    CREATE  FUNCTION [dbo].[SplitStr]
    (
     @SplitString varchar(8000)
    )
    RETURNS @SplitStringsTable TABLE
    (
     [value] varchar(8000)
    )
    AS
    BEGIN
        DECLARE @Separator varchar(2);
      
     DECLARE @CurrentIndex int;
        DECLARE @NextIndex int;
        DECLARE @ReturnText varchar(8000);-- nvarchar(4000)
        SELECT @CurrentIndex=1;
        SELECT @Separator = ',';
        WHILE(@CurrentIndex<=len(@SplitString))
        BEGIN
            SELECT @NextIndex=charindex(@Separator,@SplitString,@CurrentIndex);
            IF(@NextIndex=0 OR @NextIndex IS NULL)
                SELECT @NextIndex=len(@SplitString)+1;
           
            SELECT @ReturnText=substring(@SplitString,@CurrentIndex,@NextIndex-@CurrentIndex);
            INSERT INTO @SplitStringsTable([value])
            VALUES(@ReturnText);
           
            SELECT @CurrentIndex=@NextIndex+1;
        END
        RETURN;
    END
    -----------------------------

  2. 组织sql

    老格式:
    select t2.* from   lily_project T2 where t2.projectname in ('亚洲一号','测试')
     新格式:
     select t2.* from SplitStr('亚洲一号,测试') T1 , lily_project T2
    where t1.value = t2.projectname

    老格式:
    select t2.* from  lily_project T2 where  t2.project_id in (67,2,3)

    新格式:

    select t2.* from SplitInt('67,2,3') T1 , lily_project T2
    where t1.value = t2.project_id

  3. 配置定长参数,由于Sql Server对于不同的参数长度,会产生不过的执行路径的KEY。所以,必须要统一参数长度。这个长度可以指定为1,输入值超过1,不受影响。ibatis的inlineParameter无法设置参数长度,必须依靠ParameterMap来设置。所以,最终效果如下:

        <parameterMap id="testjoin" class="string">
            <parameter property="value" dbtype="varchar" size="1"/>
        </parameterMap>

        <select id="testJoinIn" parameterMap="testjoin" resultClass="project">        
            select t2.* from SplitInt(?) T1 , lily_project T2 where t1.value = t2.project_id
        </select>


 效果

         经过测试,使用上面的语句能提高20%的效率。另外,单个语句执行无提高效果。

其它

        受到启发,其它所有调用的时候。如果参数中有字符串的时候,一定要使用parameterMap形式,并且定义paramter的size

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值