如何使用 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 个字符?的主要内容,如果未能解决你的问题,请参考以下文章
尽管有查询字符串,但在使用 sql COUNT 时 ExecuteNonQuery 返回 -1
C# 用command.ExecuteNonQuery() 执行update语句界面卡死,也不报错!??使用的是oracle数据库