简体   繁体   English

如何连接long nvarchar(max)行来构建动态T-SQL

[英]How to concatenate long nvarchar(max) rows to build a dynamic T-SQL

I have a table in SQL Server 2012 BI: 我在SQL Server 2012 BI中有一个表:

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

loaded with parts of the very long T-SQL query stored in [Line] column. 加载了[Line]列中存储的非常长的T-SQL查询的一部分。 Example: 例:

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

The code have 60 lines, each of the line may be up to 12,000 characters because of number of the columns and their names' length. 代码有60行,由于列的数量及其名称的长度,每行最多可达12,000个字符。

I need to execute entire code built by all those rows and I don't know how to do that avoiding truncation. 我需要执行由所有这些行构建的整个代码,我不知道如何避免截断。

It can be very tricky to work with longer string. 使用更长的字符串可能非常棘手。 Check this: 检查一下:

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

Although one might think this is declared as NVARCHAR(MAX) the given 'x' isn't. 虽然有人可能认为这被声明为NVARCHAR(MAX)但给定的'x'不是。 This let's the string be a normal string with a smaller size limit. 这个字符串是一个具有较小大小限制的普通字符串。 Now try this (only difference is the CAST('x' AS NVARCHAR(MAX)) ): 现在试试这个(唯一不同的是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;

To demonstrate this I create a working example with a dummy table with 60 row each row consisting of 12.000 characters. 为了演示这一点,我创建了一个带有虚拟表的工作示例,每行包含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

The final result shows clearly, that the resulting string has the length of 60 times 12.000 (plus the added blanks) and is twice this sice in memory due to NVARCHAR . 最后的结果清楚地表明,由于NVARCHAR ,结果字符串的长度为60倍12.000(加上添加的空格)并且是内存的两倍。 Up to ~2GB this concatenation should work. 这个连接最多可达2GB。 According to this this is pretty much enough :-) 据此,这已经足够了:-)

I think, that EXEC is able to deal with NVARCHAR(MAX) up to the full size. 我认为, EXEC能够处理NVARCHAR(MAX)到全尺寸。

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

The @sql variable must be declared with MAX as length. 必须使用MAX作为长度声明@sql变量。 If the string is more than 4000, you may cannot print whole string, but it can be executed. 如果字符串超过4000,则可能无法打印整个字符串,但可以执行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM