我有一个长度为1,44,000的字符串,必须作为参数传递给存储过程,该存储过程是对表的选择查询。 当这是一个查询(在c#中)它的工作正常。但是,当我将它作为参数传递给存储过程时,它无法正常工作。
这是我的存储过程,其中我已将此参数声明为NVARCHAR(MAX)
------------------------------------------------------
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
CREATE PROCEDURE [dbo].[ReadItemData](@ItemNames NVARCHAR(MAX),@TimeStamp as DATETIME)
AS
select * from ItemData
where ItemName in (@ItemNames) AND TimeStamp=@TimeStamp
---------------------------------------------------------------------
这里的参数@ItemNames是一个用不同名称连接的字符串,例如 '项目1', '项目2', '项目3' ....等。
谁能告诉我这里出了什么问题?
谢谢&此致
帕德玛
答案 0 :(得分:5)
我意识到这是一个老问题,但我看到的问题不是字段限制,而是语法。问题是存储过程不会将参数视为要插入SELECT文本的字符串,而是在字面上查找字段中是否存在1M +字符串。有几种方法可以解决这个问题。
首先,您可以在变量中动态构建SQL,然后像这样运行它:
DECLARE @SQL as nvarchar(max)
SET @SQL = 'SELECT * FROM ItemData WHERE ItemName in (' + @ItemsNames + ')'
+ ' AND TimeStamp = ''' + @TimeStamp + ''''
EXEC (@SQL)
但是,这仍然会失败,因为@ItemNames中嵌入了引号,导致生成的SQL无效。您可以使用以下命令更改@ItemNames:
REPLACE(@ItemNames, '''', '''''')
但我没有测试过这个。这里的想法是你在字符串文本中编写转义的单引号('')以向查询处理器发送单个单引号(')。上面的REPLACE函数查看任何单引号的文本,并用两个单引号替换它们。
更强大的解决方案是创建一个Split表值函数,然后用以下内容更改IN子句:
WHERE ItemName IN (SELECT SplitText FROM dbo.Split(@ItemNames))
我假设您正在处理Split函数中的嵌入式引号。我不建议只使用REPLACE删除引号,因为引号可能是保护字符串值中的逗号。
答案 1 :(得分:3)
从数据库语法看起来它看起来像Sql Server,these are the maximum sizes of things in Sql Server。
Bytes per short string column 8,000
可能是限制器。
虽然:
每个varchar的字节数(最大值), varbinary(max),xml,text或image 第2栏^ 31-1
(即2,147,483,647)表明Sql Server会处理它,但对于ado.net。
答案 2 :(得分:1)
最高可以在VARCHAR(MAX)
属性中传递8000个字符,在NVARCAHR(MAX)
如果要传递更多信息,则需要使用“用户定义表格类型”作为参数。
步骤1:需要创建用户定义表类型。
CREATE TYPE udtt_ItemNames AS TABLE
(
Item nvarchar(100)
)
步骤2:将udtt_ItemNames用户存储过程
CREATE PROCEDURE [dbo].[ReadItemData](@ItemNames udtt_ItemNames readonly,@TimeStamp as DATETIME)
AS
select * from ItemData
where ItemName in (select Item from @ItemNames) AND TimeStamp=@TimeStamp
所以现在你需要在执行存储过程时传递Table。