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,’,'))";

     

  • 相关阅读:
    59
    58
    57
    56
    55
    54
    53
    转 Using $.ajaxPrefilter() To Configure AJAX Requests In jQuery 1.5
    jquery用正则表达式验证密码强度
    什么是高内聚、低耦合?(转载)
  • 原文地址:https://www.cnblogs.com/baoconghui/p/3283775.html
Copyright © 2011-2022 走看看