在CTE中使用子查询,以便我可以使用递归

时间:2016-09-01 13:56:47

标签: sql-server recursion

我需要将文本行连接成1个字符串。我不想使用FOR XML PATH,因为我需要纯文本而不是XML。 我认为使用递归CTE可以解决这个问题,但我需要在CTE中使用子查询来创建基本案例,并且CTE中的递归案例无法识别子查询表。

这是我的SQL:

$groupBox1 = New-Object System.Windows.Forms.GroupBox
$groupBox1.Location = '10,10' 
$groupBox1.size = '400,150'
$groupBox1.text = "Title groupBox1"
$groupBox1.Visible = $true
$form1.Controls.Add($groupBox1)           # line moved here.

问题是子查询表ScriptTbl2在递归情况下无法识别。我怎样才能解决这个问题呢?

目标是将ColumnScript文本连接成每个表的1行文本。

更新 数据并不重要。我只想将多行文本连接成一行。 1表1 Text1 2表1 Text2 3表1 Text3 4表2 Text4 5表2 Text5

使用CTE递归或其他类型的查询更改为: 1表1 Text1 Text2 Text3 2表2 Text4 Text5

更新 我创建了一个临时表,需要Row_Number用于递归和3个文本字段。

DECLARE @EndCreateTableScript varchar(20) = ') ON [PRIMARY] ';
DECLARE @NewLine varchar(2) = CHAR(13) + CHAR(10);
DECLARE @createTableScript varchar(max)
SET @createTableScript = 'CREATE TABLE [' 


;WITH CTE
AS (
    SELECT ScriptTbl2.RowNumber, ScriptTbl2.CreateTableStart, ScriptTbl2.ColumnScript, ScriptTbl2.EndTableScript
    FROM
        (
            SELECT ROW_NUMBER() OVER (PARTITION BY TableName ORDER BY TableName) AS RowNumber, TableName, 
                    CreateTableStart, ColumnTextStart + DataSizeText + ColumnNullText + @NewLine AS ColumnScript, @EndCreateTableScript + TextImageScript AS EndTableScript
            FROM
            (
                SELECT DISTINCT SchemaName, TableName, @createTableScript + SchemaName + '].[' + TableName + '] ( ' + @NewLine AS CreateTableStart,
                    '[' +ColName + '] [' + DataType + '] ' AS ColumnTextStart,  
                    CASE WHEN DataType in ('bit', 'int', 'money', 'datetime') THEN ' '
                         WHEN DataType in ('numeric', 'decimal') THEN '(' + DataTypePrecision + ', ' + DataTypeScale + ') '
                         WHEN CAST(DataTypeMaxLength AS INT) = -1 THEN '(max) '
                         WHEN DataType in ('varchar', 'varbinary') THEN '('+ DataTypeMaxLength +') '
                         WHEN DataType = 'nvarchar' THEN  '('+ CAST(CAST(DataTypeMaxLength AS INT)/2 AS varchar(5)) +') '
                    END AS DataSizeText,    
                    CASE IsColumnNullable WHEN '0' THEN 'NOT NULL,' ELSE 'NULL,' END AS ColumnNullText,
                    CASE WHEN TextImageFileGroup IS NOT NULL THEN 'TEXTIMAGE_ON [' + TextImageFileGroup + ']' ELSE '' END AS TextImageScript                                                                                                 
                FROM #DBObjectsToAdd
            ) AS ScriptTbl
        ) AS ScriptTbl2
    WHERE RowNumber = 1
    UNION ALL
    SELECT CTE.RowNumber, CTE.CreateTableStart, CTE.ColumnScript + ' ' + ScriptTbl2.ColumnScript, CTE.EndTableScript 
    FROM CTE JOIN #DBObjectsToAdd ScriptTbl ON CTE.RowNumber = ScriptTbl2.RowNumber + 1
    )
    SELECT *
    FROM CTE

这是添加数据的CREATE TABLE #TableScripts(RowNumber int, TableStart varchar(100), ColumnScript varchar(max), TableEnd varchar(100)) 查询。

SELECT

出于某种原因,将SELECT RowNumber, TableName, CreateTableStart, ColumnScript, TextImageScript FROM ( SELECT DISTINCT ROW_NUMBER() OVER (PARTITION BY TableName ORDER BY TableName) AS RowNumber, SchemaName, TableName, @createTableScript + SchemaName + '].[' + TableName + '] ( ' + @NewLine AS CreateTableStart, ('[' +ColName + '] [' + DataType + '] ') + (CASE WHEN DataType in ('bit', 'int', 'money', 'datetime') THEN ' ' WHEN DataType in ('numeric', 'decimal') THEN '(' + DataTypePrecision + ', ' + DataTypeScale + ') ' WHEN CAST(DataTypeMaxLength AS INT) = -1 THEN '(max) ' WHEN DataType in ('varchar', 'varbinary') THEN '('+ DataTypeMaxLength +') ' WHEN DataType = 'nvarchar' THEN '('+ CAST(CAST(DataTypeMaxLength AS INT)/2 AS varchar(5)) +') ' END) + (CASE IsColumnNullable WHEN '0' THEN 'NOT NULL,' ELSE 'NULL,' END) + @NewLine AS ColumnScript, @EndCreateTableScript + (CASE WHEN TextImageFileGroup IS NOT NULL THEN 'TEXTIMAGE_ON [' + TextImageFileGroup + ']' ELSE '' END) AS TextImageScript FROM #DBObjectsToAdd ) AS ScriptTbl ORDER BY TableName 函数添加到查询会将其中一个表的行数从2(仅有2列)增加到32。

1 个答案:

答案 0 :(得分:0)

我认为这只是递归部分中JOIN的错误引用,但这不是问题。

您正在引用CTE,它可以被认为是递归的上一次迭代。但是对于你的“当前迭代”,你试图引用ScriptTbl2,但是ScriptTbl2只存在于“anchor”查询中 - 你必须用ROW_NUMBER()等重做那个查询,以便在递归部分中构建你自己的ScriptTbl2

也许是这样的:

DECLARE @EndCreateTableScript varchar(20) = ') ON [PRIMARY] ';
DECLARE @NewLine varchar(2) = CHAR(13) + CHAR(10);
DECLARE @createTableScript varchar(max)
SET @createTableScript = 'CREATE TABLE [' 


;WITH CTE
AS (
    SELECT ScriptTbl2.RowNumber, ScriptTbl2.CreateTableStart, ScriptTbl2.ColumnScript, ScriptTbl2.EndTableScript
    FROM
        (
            SELECT ROW_NUMBER() OVER (PARTITION BY TableName ORDER BY TableName) AS RowNumber, TableName, 
                    CreateTableStart, ColumnTextStart + DataSizeText + ColumnNullText + @NewLine AS ColumnScript, @EndCreateTableScript + TextImageScript AS EndTableScript
            FROM
            (
                SELECT DISTINCT SchemaName, TableName, @createTableScript + SchemaName + '].[' + TableName + '] ( ' + @NewLine AS CreateTableStart,
                    '[' +ColName + '] [' + DataType + '] ' AS ColumnTextStart,  
                    CASE WHEN DataType in ('bit', 'int', 'money', 'datetime') THEN ' '
                         WHEN DataType in ('numeric', 'decimal') THEN '(' + DataTypePrecision + ', ' + DataTypeScale + ') '
                         WHEN CAST(DataTypeMaxLength AS INT) = -1 THEN '(max) '
                         WHEN DataType in ('varchar', 'varbinary') THEN '('+ DataTypeMaxLength +') '
                         WHEN DataType = 'nvarchar' THEN  '('+ CAST(CAST(DataTypeMaxLength AS INT)/2 AS varchar(5)) +') '
                    END AS DataSizeText,    
                    CASE IsColumnNullable WHEN '0' THEN 'NOT NULL,' ELSE 'NULL,' END AS ColumnNullText,
                    CASE WHEN TextImageFileGroup IS NOT NULL THEN 'TEXTIMAGE_ON [' + TextImageFileGroup + ']' ELSE '' END AS TextImageScript                                                                                                 
                FROM #DBObjectsToAdd
            ) AS ScriptTbl
        ) AS ScriptTbl2
    WHERE RowNumber = 1
    UNION ALL
    SELECT CTE.RowNumber, CTE.CreateTableStart, CTE.ColumnScript + ' ' + ScriptTbl2.ColumnScript, CTE.EndTableScript 
    FROM CTE JOIN (
        SELECT ScriptTbl2.RowNumber, ScriptTbl2.CreateTableStart, ScriptTbl2.ColumnScript, ScriptTbl2.EndTableScript
        FROM (
            SELECT ROW_NUMBER() OVER (PARTITION BY TableName ORDER BY TableName) AS RowNumber, TableName, 
                    CreateTableStart, ColumnTextStart + DataSizeText + ColumnNullText + @NewLine AS ColumnScript, @EndCreateTableScript + TextImageScript AS EndTableScript
            FROM
            (
                SELECT DISTINCT SchemaName, TableName, @createTableScript + SchemaName + '].[' + TableName + '] ( ' + @NewLine AS CreateTableStart,
                    '[' +ColName + '] [' + DataType + '] ' AS ColumnTextStart,  
                    CASE WHEN DataType in ('bit', 'int', 'money', 'datetime') THEN ' '
                         WHEN DataType in ('numeric', 'decimal') THEN '(' + DataTypePrecision + ', ' + DataTypeScale + ') '
                         WHEN CAST(DataTypeMaxLength AS INT) = -1 THEN '(max) '
                         WHEN DataType in ('varchar', 'varbinary') THEN '('+ DataTypeMaxLength +') '
                         WHEN DataType = 'nvarchar' THEN  '('+ CAST(CAST(DataTypeMaxLength AS INT)/2 AS varchar(5)) +') '
                    END AS DataSizeText,    
                    CASE IsColumnNullable WHEN '0' THEN 'NOT NULL,' ELSE 'NULL,' END AS ColumnNullText,
                    CASE WHEN TextImageFileGroup IS NOT NULL THEN 'TEXTIMAGE_ON [' + TextImageFileGroup + ']' ELSE '' END AS TextImageScript                                                                                                 
                FROM #DBObjectsToAdd
            ) AS ScriptTbl
        ) AS ScriptTbl2
    ) AS ScriptTbl3
    ON ScriptTbl3.RowNumber = CTE.RowNumber + 1 --you want each iteration to increase, right?
)
SELECT *
FROM CTE