所以我在MS SQL Server 2008中编写了一个存储过程。这是一个非常长的查询,我必须动态编写它,所以我创建了一个名为@Query
的变量,并使其为{{1}类型}。现在,我已经告诉在现代版本的SQL Server中,NVARCHAR(MAX)
可以容纳大量的数据,超过最初的4000个字符。但是,当我尝试将其打印出来时,NVARCHAR(MAX)
仍会被截断为4000个字符。
@Query
我做错了什么,或者我对DECLARE @Query NVARCHAR(max);
SET @Query = 'SELECT...' -- some of the query gets set here
SET @Query = @Query + '...' -- more query gets added on, etc.
-- later on...
PRINT LEN(@Query) -- Prints out 4273, which is correct as far as I can tell
PRINT @Query -- Truncates value to 4000 characters
EXEC sp_executesql @Query -- totally crashes due to malformed (truncated) query
的工作原理完全错了?
答案 0 :(得分:57)
问题似乎与SET语句有关。我认为表达式的大小不能超过4,000个字节。如果你要做的就是分配一个超过4,000个字符的动态生成语句,则无需对任何设置进行任何更改。你需要做的是分割你的作业。如果您的语句长度为6,000个字符,请找到逻辑断点,然后将后半部分连接到同一个变量。例如:
SET @Query = 'SELECT ....' [Up To 4,000 characters, then rest of statement as below]
SET @Query = @Query + [rest of statement]
现在正常运行您的查询,即EXEC ( @Query )
答案 1 :(得分:55)
如果你有连接的Unicode / nChar / nVarChar值,那么SQL Server将隐式地将你的字符串转换为nVarChar(4000),遗憾的是它太愚蠢了,以至于它会截断你的字符串甚至给你一个警告数据已被截断!
当连接长字符串(或你感觉可能很长的字符串)总是预先连接你的字符串构建与 CAST(''作为nVarChar(MAX)),如下所示:< / p>
SET @Query = CAST('' as nVarChar(MAX))--Force implicit conversion to nVarChar(MAX)
+ 'SELECT...'-- some of the query gets set here
+ '...'-- more query gets added on, etc.
认为这就是SQL Server的工作方式真是太痛苦和可怕了。的:(强>
我知道网上的其他解决方法是说使用多个变量将代码分解为多个SET / SELECT分配,但鉴于上述解决方案,这是不必要的。
对于那些最多达到8000个字符的人,可能是因为你没有Unicode,所以它被隐式转换为VarChar(8000)。
说明:
幕后发生的事情是,即使您指定的变量使用(MAX),SQL Server也会评估您首先分配的值的右侧,默认为nVarChar(4000)或VarChar(8000)(取决于在你连接什么)。完成后计算出值(并在为你截断之后),然后在将其赋值给变量时将其转换为(MAX),但到那时为时已晚。
答案 2 :(得分:12)
要查看生成的动态SQL,请更改为文本模式(快捷方式: Ctrl-T),然后使用SELECT
PRINT LEN(@Query) -- Prints out 4273, which is correct as far as I can tell
--SET NOCOUNT ON
SELECT @Query
至于sp_executesql
,尝试这个(在文本模式下),它应该显示三个aaaaa...
,其中中间的一个是最长的,并添加了'SELECT ..'。观看右下方状态栏中的Ln... Col..
指示符,显示第二个输出结尾处的4510。
declare @n nvarchar(max)
set @n = REPLICATE(convert(nvarchar(max), 'a'), 4500)
SET @N = 'SELECT ''' + @n + ''''
print @n -- up to 4000
select @n -- up to max
exec sp_Executesql @n
答案 3 :(得分:5)
文本结果最多只允许8192个字符。
我使用这种方法
DECLARE @Query NVARCHAR(max);
set @Query = REPLICATE('A',4000)
set @Query = @Query + REPLICATE('B',4000)
set @Query = @Query + REPLICATE('C',4000)
set @Query = @Query + REPLICATE('D',4000)
select LEN(@Query)
SELECT @Query /*Won't contain any "D"s*/
SELECT @Query as [processing-instruction(x)] FOR XML PATH /*Not truncated*/
答案 4 :(得分:4)
您的第一个问题是PRINT
声明的限制。我不确定为什么sp_executesql
失败了。它应该支持几乎任何长度的输入。
查询格式错误的原因可能不是截断。
答案 5 :(得分:1)
我今天遇到了同样的问题,发现超过4000个字符限制,我不得不将动态查询拆分为两个字符串,并在执行查询时将它们连接起来。
DECLARE @Query NVARCHAR(max);
DECLARE @Query2 NVARCHAR(max);
SET @Query = 'SELECT...' -- some of the query gets set here
SET @Query2 = '...' -- more query gets added on, etc.
EXEC (@Query + @Query2)
答案 6 :(得分:1)
使用此PRINT BIG
函数输出所有内容:
IF OBJECT_ID('tempdb..#printBig') IS NOT NULL
DROP PROCEDURE #printBig
GO
CREATE PROCEDURE #printBig (
@text NVARCHAR(MAX)
)
AS
--DECLARE @text NVARCHAR(MAX) = 'YourTextHere'
DECLARE @lineSep NVARCHAR(2) = CHAR(13) + CHAR(10) -- Windows \r\n
DECLARE @off INT = 1
DECLARE @maxLen INT = 4000
DECLARE @len INT
WHILE @off < LEN(@text)
BEGIN
SELECT @len =
CASE
WHEN LEN(@text) - @off - 1 <= @maxLen THEN LEN(@text)
ELSE @maxLen
- CHARINDEX(REVERSE(@lineSep), REVERSE(SUBSTRING(@text, @off, @maxLen)))
- LEN(@lineSep)
+ 1
END
PRINT SUBSTRING(@text, @off, @len)
--PRINT '@off=' + CAST(@off AS VARCHAR) + ' @len=' + CAST(@len AS VARCHAR)
SET @off += @len + LEN(@lineSep)
END
来源:
答案 7 :(得分:1)
Print将varchar(MAX)截断为8000,nvarchar(MAX)为4000个字符。
但;
PRINT CAST(@query AS NTEXT)
将打印整个查询。
答案 8 :(得分:1)
使用字符串表达式创建动态SQL的问题是SQL确实将字符串表达式的计算限制为4,000个字符。您可以将更长的字符串分配给nvarchar(max)变量,但只要在表达式中包含+(例如+ CASE ... END +),表达式结果就会限制为4,000个字符。
解决此问题的一种方法是使用CONCAT而不是+。例如:
SET @sql = CONCAT(@sql, N'
... dynamic SQL statements ...
', CASE ... END, N'
... dynamic SQL statements ...
')
其中@sql被声明为nvarchar(max)。
答案 9 :(得分:0)
我正在创建一个JSON-LD来创建站点审查脚本。
**DECLARE @json VARCHAR(MAX);**
的实际JSON约为94K。
我通过使用CAST(''AS VARCHAR(MAX))+ @json使它起作用,如其他贡献者所述:
所以**SET @json = CAST('' AS VARCHAR(MAX)) + (SELECT .....**
2 /我还必须更改查询选项:- 查询选项->“结果”->“网格”->“接收的最大字符”->“非XML数据”设置为2000000。 (我将“ 结果”->“文本”->“每列中显示的最大字符数”保留为默认值)