【问题标题】:Exception executing a stored procedure with CASE switching from C# (T-SQL)从 C# (T-SQL) 切换 CASE 时执行存储过程的异常
【发布时间】:2010-10-26 00:01:40
【问题描述】:

我在表中有一个 NVARCHAR(max) 列和一个存储过程,它将使用 CASE 切换更新该列以及表中的任何其他列:

CREATE PROCEDURE updateTable
   @columnName sysname,
   @value nvarchar(max)
AS 
   UPDATE [dbo].[TestTable]
   SET 
      BigNvarcharValue = CASE @columnName WHEN 'BigNvarcharValue' THEN @value ELSE BigNvarcharValue END,  
      TableName = CASE @columnName WHEN 'TableName' THEN @value ELSE TableName END

如果我使用 SQL Management Studio 执行此过程,一切都会好起来的

EXEC [dbo].[updateTable]
     @columnName = 'BigNvarcharValue',
     @value = N'SOME BIG 80Kb value'

我也可以使用相同的存储过程从 C# 代码更新 TableName,但是当从 C# 更新这个 BigNvarcharValue 时,它​​会失败并返回 SQLException,即“字符串或二进制数据将被截断”。现在,我认为它与此存储过程中的 CASE 有关,因为当我将其分解为更简单的存储过程时,一切正常:

CREATE PROCEDURE updateTable   
     @columnName sysname,   
     @value nvarchar(max)
AS       
   UPDATE [dbo].[TestTable]   
   SET BigNvarcharValue=@value

我阅读了一堆论坛帖子,这些帖子描述了尝试将更大的值插入 NVARCHAR 列的问题,这会导致此异常,但它似乎并不适用。

我是 T-SQL 的新手,所以 CASE 有什么我不知道的限制吗?

附: BigNvarcharValue 是 NVARCHAR(MAX) 并且 TableName 是 NVARCHAR(50)

【问题讨论】:

  • BigNvarcharValueTableName的SQL类型是什么?另外,您为什么要以这种非常不寻常的方式进行更新?
  • 听起来问题出在 C# 代码
  • SqlParameter 上设置的 size 属性是什么
  • @Conrad - 我尝试将其设置为所有内容 - 4000、8000、Int32.MaxValue,同样的问题......让我抓狂的是,如果我执行所有单元测试,单元测试就会通过批量(具有相同的精确设置!)如果我自己执行它会抛出......可能会像这样失去我所有的头发......
  • @Andrew - BigNvarcharValue 是 NVARCHAR(MAX),TableName 是 NVARCHAR(50)。如果不使用动态 sql,您将如何只有 1 个存储过程来更新表中的所有列?

标签: sql-server tsql case-when


【解决方案1】:

您正在处理的列的数据类型是什么?因为我通过尝试将 NVARCHAR(max) 允许的值插入到 VARCHAR(50) 列中来重现错误。

重申一下 - NVARCHAR(max) 允许您指定比规定的数据类型更长的值,这就是您收到截断错误的原因。

【讨论】:

  • BigNvarcharValue 为 NVARCHAR(MAX),TableName 为 NVARCHAR(50)。
  • @kateroh:那么当您更新 tablename 值时,错误可能(并且确实)发生。
  • 不,只有当我更新另一个 NVARCHAR(MAX) 值时才会发生这种情况。我对两者都有单元测试,显然两者都在经历相同的存储过程。该名称已成功更新,任何其他不是 NVARCHAR(MAX) 的列也是如此,并且该列没有。这就是为什么它如此奇怪:(
  • @kateroh:我不明白这是怎么回事,除非您将数据类型倒置,或者 CASE 语句相反。
  • @OMG Ponies - 最糟糕的是,如果与其他测试一起批量执行单元测试(也通过相同的存储过程进行更新!),单元测试通过了... Urghhh
【解决方案2】:

错误本身说明,“字符串或二进制数据将被截断”。这意味着您插入的值似乎比nvarchar(max) 可以处理的更大。

SSMS 2008 具有一些调试功能,允许设置断点等。

我认为您可能希望关注System.String 的最大容量。这只是长度的问题,在某个地方。

【讨论】:

    【解决方案3】:

    使用您完全相同的存储过程和您描述的表,我运行了以下代码

    class Program
        {
        static void Main(string[] args)
        {
    
            using(SqlConnection cnn = new SqlConnection(@"Server=.;Database=test;Trusted_Connection=True;"))
            {
                cnn.Open();
                SqlCommand cmd = new SqlCommand("updateTable",cnn);
                cmd.CommandType = System.Data.CommandType.StoredProcedure;
                cmd.Parameters.Add(new SqlParameter("@columnName",
                       System.Data.SqlDbType.NVarChar, 128));
    
                cmd.Parameters["@columnName"].Value = "BigNvarcharValue";
    
                cmd.Parameters.Add(new SqlParameter("@value",  
                         System.Data.SqlDbType.NVarChar, -1));
                cmd.Parameters["@value"].Value = new string('T', 80000);
    
                cmd.ExecuteNonQuery();
    
    
    
            }
    
        }
    }
    

    效果很好。我会检查命令文本和参数集合(名称和值)并验证每一个是否如您所想。

    【讨论】:

      【解决方案4】:

      感谢大家的回复。我最终将大列的更新分离到一个单独的过程中,从而解决了这个问题。我确定罪魁祸首是 CASE 声明。

      【讨论】:

        猜你喜欢
        • 2015-10-25
        • 2014-06-15
        • 1970-01-01
        • 2010-09-20
        • 2011-11-07
        • 2020-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多