Sql server 检查SqlParameter值是否在其范围内';s目标SQL列
tldnr强> 在将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语句偶尔会失败,我们希望通过边界检查来确定哪个字段太大(因为我们的服务器只告诉我们字段更新失败,而不是哪个字段)。也就是说,我们
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...."
}
}
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
值),因此已经预先验证。如果情况确实如此,那么测试它们没有额外的好处。但如果它们当前驻留在一个更通用的容器中(一个更大的Int类型,甚至一个字符串),那么在这里进行测试是合适的SMALLINT
- 如果您需要知道字符串将被截断,那么必须单独测试。至少不是作为
,而是在循环和开关中,在这种情况下只需测试字符串的长度SqlMetaData
- 不管这些测试内容如何,最好不要通过以下方式创建参数:
或甚至newsqlparameter(“fieldName”,value)
。因此,关于“在构建SqlParameters时是否应该提供精度和比例”的问题,绝对是的\u Command.parameters.AddWithValue()
另一个选项(我明天有时间更新时可以详细说明)是验证所有内容,就好像没有内置容器应该反映真实的数据库/提供者数据类型一样。因此,有两个主要考虑因素将推动实施:
- 源数据当前是强类型的还是全部序列化为字符串 及
- 是否需要知道该值是否将被截断(特别是在该值将被静默截断,而不会导致错误,从而可能导致意外行为的情况下)。这里的问题是,将数据插入表中超过指定最大长度的字段将导致
字符串或二进制数据被截断
错误。但当将数据传递给参数(即,不直接传递给表)时,该数据将被截断而不会导致错误。有时这是正常的,但有时这会导致输入参数指定不正确(或是正确的,但随后字段被扩展,参数从未更新以匹配新长度),并且可能会切断一些在客户报告之前未检测到的值的末端“有些事情在报告上看起来不太对劲,顺便说一句,这件事已经断断续续地发生了四五个月了,但我一直很忙,一直忘了提它,也许已经九个月了,我记不起来了,但是是的,有些事情不对劲“。我的意思是,我们多长时间通过传递每个参数的最大值来测试代码,以确保系统能够处理它
- 布尔->比特
- 字节->小字节
- Int16->SMALLINT
- Int32->INT
- Int64->BIGINT
- 双->浮动
- 单->实
- Guid->唯一标识符
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)