2017-03-17 28 views
3

我有一个表在SQL Server 2012中的BI:如何连接长为nvarchar(最大)行建立一个动态T-SQL

CREATE TABLE CodeParts (
    ID int identity(1,1) not null 
    ,Line nvarchar(max) not null 
) 

装载有很长的T-SQL查询的部分存储在[Line]柱。例如:

ID | Line 
---------------------- 
1 | BEGIN TRAN MERGE someTableWithLotOfColumns dst USING (SELECT... 
2 | WHEN MATCHED THEN CASE WHEN dst.someColumn != src.someColumn... 
3 | WHEN NOT MATCHED... 
4 | OUTPUT... 
5 | ;MERGE... next table with lot of columns blah blah blah 
...| ... 
25 | ;MERGE... yet another table with lot of columns 
60 | COMMIT 

该代码有60行,由于列的数量和它们的名称长度,每行可能最多12,000个字符。

我需要执行所有这些行构建的整个代码,我不知道如何避免截断。

回答

1

使用较长的字符串可能非常棘手。检查:

DECLARE @txt NVARCHAR(MAX)=(SELECT REPLICATE('x',12000)); 
SELECT LEN(@txt) AS CountCharacters 
     ,DATALENGTH(@txt) AS UsedBytes; 

尽管有人可能会认为这是声明为NVARCHAR(MAX)给出'x'不是。这让我们把字符串作为一个具有更小尺寸限制的普通字符串。现在试试这个(唯一的区别是CAST('x' AS NVARCHAR(MAX))):

DECLARE @txt2 NVARCHAR(MAX)=(SELECT REPLICATE(CAST('x' AS NVARCHAR(MAX)),12000)); 
SELECT LEN(@txt2) AS CountCharacters 
     ,DATALENGTH(@txt2) AS UsedBytes; 

为了证明这一点,我创建与60排每排由12.000字符的虚表的工作示例。

DECLARE @tbl TABLE(ID INT IDENTITY,CodeLine NVARCHAR(MAX)); 

WITH TallySixty AS (SELECT TOP 60 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS Dummy FROM master..spt_values) 
INSERT INTO @tbl 
SELECT REPLICATE(CAST(RIGHT(Dummy,1) AS NVARCHAR(MAX)),12000) 
FROM TallySixty; 

SELECT CodeLine,LEN(CodeLine) AS CountCharacters 
     ,DATALENGTH(CodeLine) AS UsedBytes FROM @tbl 

DECLARE @concatString NVARCHAR(MAX)= 
(
    SELECT(SELECT CodeLine + ' ' FROM @tbl FOR XML PATH(''),TYPE).value('(text())[1]','nvarchar(max)') 
); 

SELECT @concatString 
     ,LEN(@concatString) AS CountCharacters 
     ,DATALENGTH(@concatString) AS UsedBytes 

最后的结果清楚地表明,所得到的字符串具有60倍12.000(加上加空白)的长度和这是在SICE存储器由于NVARCHAR两次。高达〜2GB的连接应该可以工作。 According to this这是非常不够:-)

我认为,该EXEC是能够处理NVARCHAR(MAX)高达全尺寸。

+0

'nvarchar(max)'*变量*不是[限于那个讨厌的2GB限制](http://stackoverflow.com/q/7611394/15498) –

+0

@Damien_The_Unbeliever Thx!我刚刚使用'TOP 22000'和'REPLICATE'以100.000测试了我的代码(在* Tally *中有一些'CROSS JOINs'),这应该会超出* magic limit *。几乎4分钟后,我得到了异常6365 :(自己的翻译)* XML进程导致XML数据类型大于2GB。该进程已终止*。 – Shnugo

+0

是的,这似乎是(ab-)使用XML系统执行串接的限制。 –

0
DECLARE @sql NVARCHAR(max) 
SET @sql=ISNULL(@sql+CHAR(13),'')+Line FROM CodeParts order by id 
EXEC(@SQL) 

@sql变量必须以MAX作为长度声明。 如果字符串超过4000,则可能无法打印整个字符串,但可以执行。

+0

1)不保证工作,2)绝对不能保证以正确的顺序检索行,没有'ORDER BY'。但请注意(1)再次 - 和[本页](https://msdn.microsoft.com/en-GB/library/ms189484.aspx#Remarks):“不要在SELECT语句中使用变量来连接值(即计算聚合值),可能会出现意外的查询结果,这是因为SELECT列表中的所有表达式(包括赋值)不能保证每个输出行只执行一次“ –