Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 检查SqlParameter值是否在其范围内';s目标SQL列_Sql Server_C# 3.0_Sqlparameter - Fatal编程技术网

Sql server 检查SqlParameter值是否在其范围内';s目标SQL列

Sql server 检查SqlParameter值是否在其范围内';s目标SQL列,sql-server,c#-3.0,sqlparameter,Sql Server,C# 3.0,Sqlparameter,tldnr 在将SqlParameter值放入数据库之前,我应该如何检查这些值的边界 较长版本: 因此,我有这些动态生成的SQL语句,其中我传递了一组SqlParameters 我们声明SqlParameters的方法只是 new SqlParameter("fieldName", value) 我们让运行时知道dbtype是什么 也就是说,update/insert语句偶尔会失败,我们希望通过边界检查来确定哪个字段太大(因为我们的服务器只告诉我们字段更新失败,而不是哪个字段)。也就是说,我们

tldnr

在将
SqlParameter
值放入数据库之前,我应该如何检查这些值的边界

较长版本:

因此,我有这些动态生成的SQL语句,其中我传递了一组
SqlParameter
s

我们声明
SqlParameter
s的方法只是

new SqlParameter("fieldName", value)
我们让运行时知道dbtype是什么

也就是说,update/insert语句偶尔会失败,我们希望通过边界检查来确定哪个字段太大(因为我们的服务器只告诉我们字段更新失败,而不是哪个字段)。也就是说,我们不能在只允许1位(.)的列中放置两位数字

我们在内存中有列的模式(information_schema.columns ftw),因此我们可以尝试对SqlParameter值进行边界检查,但是由于该值是一个对象,甚至不一定是数字类型,我应该如何检查值是否在范围内

还是我把问题弄得太难了,反而应该在开始构建SqlParameters时提供精度和规模?或者更好,我们应该使用反映数据库中列的类型吗

更新:

如图所示,设置精度/刻度似乎没有任何后果:


似乎
SqlParameter
在设置
Value
属性时不进行验证。而且
DataColumn
不允许指定
精度
比例
,因此用处不大。但是,有一种方法:

  • 使用已有的架构信息集合,根据架构集合的大小动态创建
    SqlMetaData
    数组,并使用列名和大小数据填充该数组:

    SqlMetaData[] _TempColumns = new SqlMetaData[_SchemaCollection.Count];
    
    loop-of-some-sort
    {
       switch (_SchemaCollection.DataType)
       {
          case "decimal":
             _TempColumns[_Index] = new SqlMetaData(
                         _SchemaCollection.Name,
                         SqlDbType.Decimal,
                         (byte)_SchemaCollection.Precision, 
                         (byte)_SchemaCollection.Scale
                      );
             break;
           case "others...."
       }
    }
    
  • 使用步骤1中的
    SqlMetaData[]
    创建新的
    SqlDataRecord

    SqlDataRecord _TempRow = new SqlDataRecord(_TempColumns);
    
  • 循环执行
    \u TempRow
    调用每个位置的相应
    Set
    方法,在try/catch中:

    string _DataAintRight;
    
    try
    {
       _TempRow.SetDecimal(_Index, _SchemaCollection.Value);
    }
    catch
    {
      _DataAintRight = _SchemaCollection.Name;
      break;
    }
    
  • 注:

    • 这将只执行与将参数传递给proc相同的验证。这意味着,它将静默地截断过长的值,例如小数点右侧的数字过多,以及超过最大大小的字符串

    • 固定长度的数字类型应该已经在其等效的.Net类型中(即
      Int16
      变量或属性中的
      SMALLINT
      值),因此已经预先验证。如果情况确实如此,那么测试它们没有额外的好处。但如果它们当前驻留在一个更通用的容器中(一个更大的Int类型,甚至一个字符串),那么在这里进行测试是合适的

    • 如果您需要知道字符串将被截断,那么必须单独测试。至少不是作为
      SqlMetaData
      ,而是在循环和开关中,在这种情况下只需测试字符串的长度

    • 不管这些测试内容如何,最好不要通过以下方式创建参数:
      newsqlparameter(“fieldName”,value)
      或甚至
      \u Command.parameters.AddWithValue()
      。因此,关于“在构建SqlParameters时是否应该提供精度和比例”的问题,绝对是的


    另一个选项(我明天有时间更新时可以详细说明)是验证所有内容,就好像没有内置容器应该反映真实的数据库/提供者数据类型一样。因此,有两个主要考虑因素将推动实施:

    • 源数据当前是强类型的还是全部序列化为字符串

    • 是否需要知道该值是否将被截断(特别是在该值将被静默截断,而不会导致错误,从而可能导致意外行为的情况下)。这里的问题是,将数据插入表中超过指定最大长度的字段将导致
      字符串或二进制数据被截断
      错误。但当将数据传递给参数(即,不直接传递给表)时,该数据将被截断而不会导致错误。有时这是正常的,但有时这会导致输入参数指定不正确(或是正确的,但随后字段被扩展,参数从未更新以匹配新长度),并且可能会切断一些在客户报告之前未检测到的值的末端“有些事情在报告上看起来不太对劲,顺便说一句,这件事已经断断续续地发生了四五个月了,但我一直很忙,一直忘了提它,也许已经九个月了,我记不起来了,但是是的,有些事情不对劲“。我的意思是,我们多长时间通过传递每个参数的最大值来测试代码,以确保系统能够处理它

    如果源数据属于适当的.Net类型:

    有几个不需要检查,因为.Net和SQL Server之间的固定长度数字类型是相同的。仅通过在各自的.Net类型中存在而预先验证的有:

    • 布尔->比特
    • 字节->小字节
    • Int16->SMALLINT
    • Int32->INT
    • Int64->BIGINT
    • 双->浮动
    • 单->实
    • Guid->唯一标识符
    有一些只需要检查截断(如果这是一个问题),因为它们的值应该始终与SQL Server对应的值在同一范围内。请记住,在这里我们讨论的是严格截断,当值传递给较小规模的参数时,但实际上是r
    string _DataAintRight;
    
    try
    {
       _TempRow.SetDecimal(_Index, _SchemaCollection.Value);
    }
    catch
    {
      _DataAintRight = _SchemaCollection.Name;
      break;
    }
    
    case "smalldatetime":
      if ((_Value < range_min) || (_Value > range_max))
      {
        _ThisValueSucks = true;
      }
      break;
    
    if ((Math.Floor(_Value) < -999) || (Math.Floor(_Value) > 999))
    
    if (Math.Abs(Math.Floor(_Value)).ToString().Length <= DataTypeMaxSize)