SqlBulkCopy 截断 VARCHAR(MAX) 列中的字符串

Posted

技术标签:

【中文标题】SqlBulkCopy 截断 VARCHAR(MAX) 列中的字符串【英文标题】:SqlBulkCopy truncating string in VARCHAR(MAX) column 【发布时间】:2021-01-03 01:58:24 【问题描述】:

我在 SQL Server 2016 上有一个简单的表:

 CREATE TABLE AgentDownload 
(
  Download VARCHAR(max)
)

我正在使用以下代码使用 C# 中的 SqlBulkCopy 类填充此表。

    var agentDataTable = new DataTable();
    agentDataTable.Clear();
    agentDataTable.Columns.Add("Download");

    var agentDownloadRow = agentDataTable.NewRow();
    
    var veryLongString = "aaa..." // 200,000 a's repeated
    agentDownloadRow["Download"] = veryLongString;

    agentDataTable.Rows.Add(agentDownloadRow);

    using (var connection = new SqlConnection("Data Source=Server;Initial Catalog=Database;Integrated Security=True;"))
    
        connection.Open();
        var transaction = connection.BeginTransaction();
        
        using (var sbCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.CheckConstraints, transaction))
        
            sbCopy.BulkCopyTimeout = 0;
            sbCopy.BatchSize = 10000;
            sbCopy.DestinationTableName = "AgentDownload";
            sbCopy.WriteToServer(agentDataTable);
                            
        transaction.Commit();
    

当我检索此条目时,在数据库中,单元格值被截断为 65,535 个字符。这是某种限制,但我不确定这是从哪里来的,或者是否有任何解决方法?该列可以包含更多字符,C# 中的字符串类型也可以包含更多字符。有没有人可以做这个操作?

我认为这可能是 SqlBulkCopy 类的限制,但使用如下替代代码也会产生相同的结果:

    using (var connection = new SqlConnection("Data Source=Server;Initial Catalog=Database;Integrated Security=True;"))
    
        connection.Open();
        var transaction = connection.BeginTransaction();
        
        var cmd = connection.CreateCommand();
        cmd.Transaction = transaction;
        cmd.CommandText = "insert into AgentDownload (Download) values (CAST('' AS VARCHAR(MAX)) + @testVariable)";

        var parameter = new SqlParameter
        
            ParameterName = "testVariable",
            DbType = DbType.String,
            Size = -1,
            Value = veryLongString
        ;
        cmd.Parameters.Add(parameter);
        cmd.ExecuteNonQuery();
        transaction.Commit();
    

【问题讨论】:

“在我检索此条目时,在数据库中,单元格值被截断为 65,535 个字符。” 你在哪里看到这个?听起来像是在使用 SSMS。 @RomanRyzhiy 这个说法是完全错误的...varchar(MAX) 可以存储 2GB 的数据,大约是 2十亿 个字符。 SSMS 默认将大值截断为 65535 个字符。要查看结果网格中的整个值,请在工具-->选项-->查询结果-->SQL Server-->结果到网格下更改检索到的最大字符值。 @DanGuzman 哇,我的错。这就是问题所在。我不知道...每天都是上学日。 @Ben,我几乎没有一天不学习新东西,而且我已经使用 SQL Server 25 年了。 【参考方案1】:

您似乎正在使用 SSMS 查看批量插入的数据。 SSMS 默认将大值截断为 65535 个字符。

要在当前查询窗口的结果网格中查看整个值,请从Query-->Query Options-->Results-->Grid 下的 SSMS 菜单中更改 Max Characters Retrieved 值。

还可以为Tools-->Options-->Query Results-->SQL Server-->Results to Grid 下的所有新查询窗口指定值。但是,请考虑许多包含大值的行对客户端内存要求的影响。我建议明智地更改全局选项。

【讨论】:

以上是关于SqlBulkCopy 截断 VARCHAR(MAX) 列中的字符串的主要内容,如果未能解决你的问题,请参考以下文章

ODBC 截断 varchar 字段

SqlServer优化之批量插入(SqlBulkCopy表值参数)

SqlServer优化之批量插入(SqlBulkCopy表值参数)

MySQL 太长 varchar 截断/错误设置

VARCHAR 字段被截断为 255 个字符

使用SqlBulkCopy进行批量插入数据操作遇到的问题