如何使用 ExecuteNonQuery 在 VARCHAR(MAX) 列中插入超过 8000 个字符?

Posted

技术标签:

【中文标题】如何使用 ExecuteNonQuery 在 VARCHAR(MAX) 列中插入超过 8000 个字符?【英文标题】:How can I insert more than 8000 characters in a VARCHAR(MAX) column with ExecuteNonQuery? 【发布时间】:2012-12-30 04:52:56 【问题描述】:

我正在尝试通过ExecuteNonQuery(和来自 MS Practices Enterprise Library 的DatabaseFactory.CreateDatabase())插入 > 8000 个字符(从网页提交)。存储过程将参数定义为VARCHAR(MAX)。该列是VARCHAR(MAX)。理论上,2GB的数据应该是可以通过的。

我可以做些什么来传递> 8000的数据?我设置了一个断点,string.Length 确实 > 8K。

   public static void UpdateTerms(string terms)
   
        Database db = DatabaseFactory.CreateDatabase();
        db.ExecuteNonQuery("uspUpdateTerms", terms);
    

存储过程:

ALTER PROCEDURE [dbo].[uspUpdateTerms]
    @Terms VARCHAR(MAX)
AS
  SET NOCOUNT ON

  INSERT INTO tblTerms(Terms)
  VALUES(@Terms)

表格(只是为了表明一切都是varchar(max)):

CREATE TABLE [dbo].[tblTerms](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Terms] [varchar](max) NULL,
[DateUpdated] [datetime] NULL,

.

更新:

我刚刚更改了代码,这似乎有效,但我不确定有什么区别:

 public static void UpdateTerms(string terms)
 
        Database db = DatabaseFactory.CreateDatabase();
        DbCommand cmd = db.GetStoredProcCommand("uspUpdateTerms");
        db.AddInParameter(cmd, "Terms", DbType.String, terms);
        db.ExecuteNonQuery(cmd);
 

【问题讨论】:

有趣,如果我这样做:插入测试(数据)值(@x + @x + @x)从测试中选择数据,Len(数据)......它显示24000(不是30K) ,但显然允许 > 8K @twoleggedhorse - a 被视为varchar(1) 而不是nvarchar(8000)(甚至没有这样的数据类型) 我的意思是说 VARCHAR 不是 NVARCHAR,我已经重新发布了我的评论,因为我无法再次编辑它 @twoleggedhorse - 是什么?超过 8,000 个字符的字符串文字被视为 varchar(max)。正如现有答案已经表明的那样,这是使用REPLICATE。将varchar(1-8000) 连接到varchar(1-8000) 会导致截断。 我之前没有注意到这种行为,但是'a'(一种未声明的字符串类型)默认被视为 VARCHAR(8000),您必须将其转换为 VARCHAR(MAX)。为这个问题 +1。 【参考方案1】:

REPLICATE 返回输入类型,而不管以后的分配。这很烦人,但为了避免静默截断,请尝试:

SET @x = REPLICATE(CONVERT(VARCHAR(MAX), 'a'), 10000);

这是因为 SQL Server 会先执行 REPLICATE 操作,然后再考虑您将其分配给什么或尝试将其扩展为多少个字符。它只关心输入表达式来确定它应该返回什么,如果输入不是最大类型,它假定它应该适合 8,000 字节。这在Books Online 中有解释:

如果 string_expression 不是 varchar(max) 或 nvarchar(max) 类型,则 REPLICATE 将返回值截断为 8,000 字节。要返回大于 8,000 字节的值,必须将 string_expression 显式转换为适当的大值数据类型。

【讨论】:

我理解这个测试,但最终我该如何完成我想要做的事情,即使用 ExecuteNonQuery 从 C# 程序传递 > 8K? @Investor5555 我不知道从 C# 发送更大的查询有任何问题(尽管如果您的查询文本长于 8K,也许您应该考虑存储过程、参数化查询、表值参数,等等)。也许您的问题应该说明这个问题,而不是我们已经回答的问题?【参考方案2】:

您的示例代码可以通过以下方式修复:

declare @x varchar(max)
set @x = replicate (cast('a' as varchar(max)), 10000)
select @x, len(@x)

【讨论】:

【参考方案3】:

您尚未在尝试使用ExecutenonQuery 的位置显示代码。请注意,您应该使用参数。

using(var con = new SqlConnection(conString))
using(var cmd = new SqlCommand("storedProcedureName", con))

    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@text", SqlDbType.NVarChar, -1);
    cmd.Parameters["@text"].Value = yourVeryLongText;
    cmd.ExecuteNonQuery();

【讨论】:

这完全是一个 SQL 问题 - 默认情况下,未定义的字符串类型被视为 NVARCHAR(8000)。 @twoleggedhorse 没有 NVARCHAR(8000) 这样的东西。 public static void UpdateTerms(string terms) Database db = DatabaseFactory.CreateDatabase(); db.ExecuteNonQuery("uspUpdateTerms", 条款); @twoleggedhorse 。 . .那不是nvarchar(4000)吗? @Investor5555 请不要在 cmets 中塞进一堆代码。读起来有趣吗?更新您的问题以反映您的实际问题,或者开始一个新问题,因为已经有解决您最初描述的[非常不同]问题的答案。【参考方案4】:

问题可能不是数据的存储,可能是检索。

如果您试图通过企业管理器确定数据库中是否存储了超过 8000 个字符,那么如果您只是选择列的内容并查看文本长度,那么您就不走运了:企业管理器限制列输出。

要确定该列中实际存储了多少数据,请执行以下查询:

SELECT DATALENGTH(Terms) FROM tblTerms

这将告诉您存储了多少文本。

编辑:

刚刚出现了另一个想法:企业库缓存存储过程参数以提高性能。如果您在将参数设置为nvarchar(8000) 的测试后更改了存储过程,然后在不重置应用程序的情况下将参数切换为nvarchar(max)(如果是IIS 托管,则iisreset 或脏web.config),那么您仍然会使用旧的存储过程参数。

【讨论】:

大概就是这样。 SP 是 VARCHAR(8000),我改变了它。我把我的代码恢复到原来的样子,它也可以工作。 它一定已经被缓存了。你成功了!太棒了。

以上是关于如何使用 ExecuteNonQuery 在 VARCHAR(MAX) 列中插入超过 8000 个字符?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ExecuteNonQuery c# 时出错

c#: ExecuteNonQuery() 返回 -1

尽管有查询字符串,但在使用 sql COUNT 时 ExecuteNonQuery 返回 -1

cmd.executeNonQuery() 更新

C# 用command.ExecuteNonQuery() 执行update语句界面卡死,也不报错!??使用的是oracle数据库

使用 c#ExecuteNonQuery 插入后 MS Access 表未正确刷新