如何保持存储过程输入不被静默截断?

Nic*_*mas 5 c# sql-server error-handling stored-procedures

我们使用标准System.Data类,DbConnection并且DbCommand,从C#连接到SQL Server,我们有许多存储过程,VARCHAR或者NVARCHAR参数作为输入.我们发现,当长度超过参数最大长度的字符串作为该参数的值传入时,SQL Server和C#应用程序都不会抛出任何类型的错误或警告.而是将该值静默截断为参数的最大长度.

因此,例如,如果存储过程输入是类型VARCHAR(10)并且我们传入'U R PRETTY STUPID',则存储过程接收输入'U R PRETTY',这非常好但完全不是我们想要说的.

我过去所做的检测这些截断以及其他人同样建议的是,使参数输入长度比所需的大一个字符,然后检查输入的长度是否等于新的最大长度.因此在上面的示例中,我的输入将变为,VARCHAR(11)并且我将检查长度为11的输入.任何长度为11或更长的输入都将被此检查捕获.这有效,但感觉不对.理想情况下,数据访问层会自动检测这些问题.

有没有更好的方法来检测提供的存储过程输入是否超过允许的时间?不应该DbCommand已经知道输入长度限制?

另外,作为一个好奇心,是什么导致默默地截断我们的输入?

Rem*_*anu 3

对所有变量和参数使用VARCHAR(8000),NVARCHAR(4000)甚至, 。N/VARCHAR(MAX)这样你在分配@variables和@parameters时就不需要担心截断。截断可能会在实际数据写入(插入或更新)时发生,但这并不是无声的,会触发硬错误,您会发现它。您还可以获得存储过程代码的额外好处,而不必随着架构更改而更改(更改列长度,代码仍然有效)。您还可以通过使用一致的参数长度获得更好的计划缓存行为,请参阅数据访问代码如何影响数据库性能

请注意,对 @variables/@parameters 使用 MAX 类型会对性能造成轻微影响,请参阅varchar(max) 与 varchar(N) 的性能比较