zoukankan      html  css  js  c++  java
  • 关于SqlParameter中IN子句查询的问题

    今天调试到方法中代码:

    String hotelCodes =”’000000’,’111111’,’222222’”;
    string sqltext ="select * from HotelMedalInfo where hotelCode in(@hotelCodes)";
     SqlParameter[] parameters = {
    new SqlParameter("@hotelCodes", hotelCodes)
    };
    DataTable dt = DBHelper.ExecuteData(sqlText, parameters);
    
                if (dt == null || dt.Rows.Count <= 0)
                {
                    return null;
                }

    返回数据一直不正确。

    调试后,发现应该是ExecuteData生成的Sql有问题。于是想看看到底是怎么回事。我一步步的找到了SqlCommand下的BuildExecuteSql 方法。

    其代码如下:

      1 private void BuildExecuteSql(CommandBehavior behavior, string commandText, SqlParameterCollection parameters, ref _SqlRPC rpc)
      2 {
      3     int num;
      4     int num2 = this.CountSendableParameters(parameters);
      5     if (num2 > 0)
      6     {
      7         num = 2;
      8     }
      9     else
     10     {
     11         num = 1;
     12     }
     13     this.GetRPCObject(num2 + num, ref rpc);
     14     rpc.ProcID = 10;
     15     rpc.rpcName = "sp_executesql";
     16     if (commandText == null)
     17     {
     18         commandText = this.GetCommandText(behavior);
     19     }
     20     SqlParameter parameter = new SqlParameter(null, ((commandText.Length << 1) <= 0x1f40) ? SqlDbType.NVarChar : SqlDbType.NText, commandText.Length);
     21     parameter.Value = commandText;
     22     rpc.parameters[0] = parameter;
     23     if (num2 > 0)
     24     {
     25         string str = this.BuildParamList(this._stateObj.Parser, this.BatchRPCMode ? parameters : this._parameters);
     26         parameter = new SqlParameter(null, ((str.Length << 1) <= 0x1f40) ? SqlDbType.NVarChar : SqlDbType.NText, str.Length);
     27         parameter.Value = str;
     28         rpc.parameters[1] = parameter;
     29         bool inSchema = CommandBehavior.Default != (behavior & CommandBehavior.SchemaOnly);
     30         this.SetUpRPCParameters(rpc, num, inSchema, parameters);
     31     }
     32 }
     33 
     34 其中有用到BuildParamList方法:
     35 
     36 internal string BuildParamList(TdsParser parser, SqlParameterCollection parameters)
     37 {
     38     StringBuilder builder = new StringBuilder();
     39     bool flag = false;
     40     bool isYukonOrNewer = parser.IsYukonOrNewer;
     41     int count = 0;
     42     count = parameters.Count;
     43     for (int i = 0; i < count; i++)
     44     {
     45         SqlParameter p = parameters[i];
     46         p.Validate(i, CommandType.StoredProcedure == this.CommandType);
     47         if (ShouldSendParameter(p))
     48         {
     49             if (flag)
     50             {
     51                 builder.Append(',');
     52             }
     53             builder.Append(p.ParameterNameFixed);
     54             MetaType internalMetaType = p.InternalMetaType;
     55             builder.Append(" ");
     56             if (internalMetaType.SqlDbType == SqlDbType.Udt)
     57             {
     58                 string udtTypeName = p.UdtTypeName;
     59                 if (ADP.IsEmpty(udtTypeName))
     60                 {
     61                     throw SQL.MustSetUdtTypeNameForUdtParams();
     62                 }
     63                 builder.Append(this.ParseAndQuoteIdentifier(udtTypeName, true));
     64             }
     65             else if (internalMetaType.SqlDbType == SqlDbType.Structured)
     66             {
     67                 string typeName = p.TypeName;
     68                 if (ADP.IsEmpty(typeName))
     69                 {
     70                     throw SQL.MustSetTypeNameForParam(internalMetaType.TypeName, p.ParameterNameFixed);
     71                 }
     72                 builder.Append(this.ParseAndQuoteIdentifier(typeName, false));
     73                 builder.Append(" READONLY");
     74             }
     75             else
     76             {
     77                 internalMetaType = p.ValidateTypeLengths(isYukonOrNewer);
     78                 builder.Append(internalMetaType.TypeName);
     79             }
     80             flag = true;
     81             if (internalMetaType.SqlDbType == SqlDbType.Decimal)
     82             {
     83                 byte actualPrecision = p.GetActualPrecision();
     84                 byte actualScale = p.GetActualScale();
     85                 builder.Append('(');
     86                 if (actualPrecision == 0)
     87                 {
     88                     if (this.IsShiloh)
     89                     {
     90                         actualPrecision = 0x1d;
     91                     }
     92                     else
     93                     {
     94                         actualPrecision = 0x1c;
     95                     }
     96                 }
     97                 builder.Append(actualPrecision);
     98                 builder.Append(',');
     99                 builder.Append(actualScale);
    100                 builder.Append(')');
    101             }
    102             else if (internalMetaType.IsVarTime)
    103             {
    104                 byte num6 = p.GetActualScale();
    105                 builder.Append('(');
    106                 builder.Append(num6);
    107                 builder.Append(')');
    108             }
    109             else if (((!internalMetaType.IsFixed && !internalMetaType.IsLong) && ((internalMetaType.SqlDbType != SqlDbType.Timestamp) && (internalMetaType.SqlDbType != SqlDbType.Udt))) && (SqlDbType.Structured != internalMetaType.SqlDbType))
    110             {
    111                 int size = p.Size;
    112                 builder.Append('(');
    113                 if (internalMetaType.IsAnsiType)
    114                 {
    115                     object coercedValue = p.GetCoercedValue();
    116                     string str = null;
    117                     if ((coercedValue != null) && (DBNull.Value != coercedValue))
    118                     {
    119                         str = coercedValue as string;
    120                         if (str == null)
    121                         {
    122                             SqlString str4 = (coercedValue is SqlString) ? ((SqlString) coercedValue) : SqlString.Null;
    123                             if (!str4.IsNull)
    124                             {
    125                                 str = str4.Value;
    126                             }
    127                         }
    128                     }
    129                     if (str != null)
    130                     {
    131                         int num4 = parser.GetEncodingCharLength(str, p.GetActualSize(), p.Offset, null);
    132                         if (num4 > size)
    133                         {
    134                             size = num4;
    135                         }
    136                     }
    137                 }
    138                 if (size == 0)
    139                 {
    140                     size = internalMetaType.IsSizeInCharacters ? 0xfa0 : 0x1f40;
    141                 }
    142                 builder.Append(size);
    143                 builder.Append(')');
    144             }
    145             else if ((internalMetaType.IsPlp && (internalMetaType.SqlDbType != SqlDbType.Xml)) && (internalMetaType.SqlDbType != SqlDbType.Udt))
    146             {
    147                 builder.Append("(max) ");
    148             }
    149             if (p.Direction != ParameterDirection.Input)
    150             {
    151                 builder.Append(" output");
    152             }
    153         }
    154     }
    155     return builder.ToString();
    156 }
    View Code

    看到这里我有点明白为什么了。原来其内部根据参数构建sql时用到了‘,’。我们为参数中包含的逗号,应该是被它误解或者屏蔽了。

    对此,我们可以创建一个函数,根据字符串hotelCodes,返回一个表。Sql条件根据函数的结果来判断。

    1.创建函数

    CREATE   FUNCTION   [dbo].[f_split](@c   varchar(2000),@split   varchar(2))  
      returns   @t   TABLE(col   varchar(20))  
      AS  
        begin  
          while(charindex(@split,@c)<>0)  
            begin  
              INSERT   @t(col)   VALUES   (substring(@c,1,charindex(@split,@c)-1))  
              SET   @c   =   stuff(@c,1,charindex(@split,@c),'')  
            end  
          INSERT   @t(col)   VALUES   (@c)  
          RETURN  
        end  
    GO
    

    2.程序sql文本部分做如下修改:

      string sqltext ="select * from HotelMedalInfo where hotelCode in (select * from dbo.f_split(@hotelCodes,’,'))";

     

  • 相关阅读:
    实例属性 类属性 实例域 类域
    研究数据集
    static 静态域 类域 静态方法 工厂方法 he use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class 非访问修饰符
    accessor mothod mutator mothod 更改器方法 访问器方法 类的方法可以访问类的任何一个对象的私有域!
    上钻 下钻 切片 转轴 降采样
    识别会话
    Performance Tuning Using Linux Process Management Commands
    Secure Hash Algorithm 3
    grouped differently across partitions
    spark 划分stage Wide vs Narrow Dependencies 窄依赖 宽依赖 解析 作业 job stage 阶段 RDD有向无环图拆分 任务 Task 网络传输和计算开销 任务集 taskset
  • 原文地址:https://www.cnblogs.com/baoconghui/p/3283775.html
Copyright © 2011-2022 走看看