2016-09-01 1 views
0

Ich muss Reihen von Text in 1 Zeichenfolge verketten. Ich möchte FOR XML PATH nicht verwenden, weil ich es im Klartext und nicht in XML benötige. Ich denke, die Verwendung eines rekursiven CTE wird den Trick tun, aber ich muss eine Unterabfrage innerhalb der CTE verwenden, um den Basisfall zu erstellen, und die Unterabfragetabelle wird nicht durch den rekursiven Fall in der CTE erkannt.Verwenden Sie Unterabfrage in einem CTE, so dass ich Rekursion verwenden kann

Das ist mein SQL:

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 

Das Problem ist, dass die Unterabfrage Tabelle, ScriptTbl2 im rekursiven Fall erkannt wird. Wie kann ich dieses Problem umgehen?

Ziel ist es, den ColumnScript-Text in 1 Zeile Text für jede Tabelle zu verketten.

UPDATE Die Daten sind nicht wichtig. Ich möchte nur mehrere Zeilen Text in 1 Zeile verketten. 1 Tab.1 Text1 2 Tabelle1 Text2 3 Tabelle1 Text3 4 Table2 Text4 5 Table2 Text5

Verwendung CTE Rekursion oder eine andere Art der Abfrage Änderung: 1 Tab.1 Text1 Text2 Text3 2 Table2 Text4 Text5

UPDATE Ich erstellte eine temporäre Tabelle, die die Row_Number für die Rekursion und 3 Textfelder benötigt.

CREATE TABLE #TableScripts(RowNumber int, TableStart varchar(100), ColumnScript varchar(max), TableEnd varchar(100)) 

Dies ist die SELECT Abfrage, die Daten hinzufügt.

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 

Aus irgendeinem Grund Hinzufügen der ROW_NUMBER Funktion auf die Abfrage erhöht sich die Anzahl der Zeilen 1 der Tabellen 2 (es hat nur 2 Spalten) bis 32.

+1

Warum wollen Sie hier nicht FOR XML verwenden? Das ist der Weg, um so etwas zu tun. –

+0

Der von XML erstellte Text fügt diese Sonderzeichen hinzu, wenn eine neue Zeile oder '<' or '>' –

+0

ist. Könnten Sie bitte Tabellendaten und erwartete Ausgaben veröffentlichen? –

Antwort

0

Ich dachte, es war nur ein schlechte referenz auf dem JOIN im rekursiven Teil, aber das ist nicht ganz das Problem.

Sie verweisen auf CTE, was als die vorherige Iteration der Rekursion angesehen werden kann. Aber für Ihre "aktuelle Iteration" versuchen Sie, ScriptTbl2 zu referenzieren, aber ScriptTbl2 existiert nur innerhalb der "Anker" -Abfrage - Sie müssen diese Abfrage mit ROW_NUMBER() wiederholen, um Ihre eigene ScriptTbl2 im rekursiven Teil aufzubauen .

Vielleicht so:

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 
+0

Wenn ich die Änderung, die 'RowNumber' kann nicht auflösen, weil es nicht existiert und' ScriptTbl2' nicht existiert in der 'SELECT' –

+0

@GloriaSantin Antwort vollständig aktualisiert, sehen, ob das hilft – SlimsGhost

+0

natürlich können Sie die gemeinsame Refactoring Abfrage in eine Ansicht, etc., aber versuchen, die Anker-Abfrage wieder zu verwenden ist die unmittelbare Sache zu beheben, ich denke, – SlimsGhost