2016-07-26 15 views
0

hoffe, das ist nicht zu grundlegend für eine Frage.Erstellen von Tabellen basierend auf SchemaColumn & SchemaTable Composite-Tabelle

Ich wollte eine neue Reihe von Tabellen in einer Datenbank mit einer gespeicherten Prozedur und einer Build-Tabelle erstellen.

Die Build-Tabelle enthält die folgenden Spalten und einige Beispielreihen:

tblNm colNm  colTyp colLen colReq colWarning colUni colComUni 
account personID Decimal NULL 0  0   0  0 
account studentNum String 15  0  0   0  0 

I wurde unter Verwendung von Multiple Cursors als eine Form von verschachteltem looping bedenkt, aber ich kann nicht herausfinden, wie die Säulenparameter in den verschachtelten definieren Prozedur, weil Cursor nur einen Wert zurückgeben.

Ich weiß, ich muss eine alter-Anweisung erstellen, die diese Werte analysiert, aber ich bin in einer mentalen Blockade. Alle Tutorials, die aufschlussreich sein könnten, würden sehr geschätzt werden

Vielen Dank im Voraus.

+0

Was bedeuten die Werte in 'colReq colWarning colUni colComUni'? –

+0

colReq = Darf nicht null sein colWarning = ob eine benutzerdefinierte Warnung in der Anwendung für Datenprobleme existiert, die die Validierung nicht scheitert colUni = muss eindeutig sein colComUni = hat eine Kombination von Feldern Wert, der eindeutig sein muss – MKasper

+0

Ok, so ColReq 0 ist Nullable und 1 ist nicht Nullable. Was ist mit Warnung, Uni und den anderen Spalten? –

Antwort

3

Sie können das Problem lösen, indem Sie zwei Cursor oder einen Cursor verwenden. Zwei Cursor machen den Code lesbarer. Ein Cursor wird effizienter.

zwei Cursor

Der folgende Code zeigt, wie zwei Cursor verwenden, um die Tabellen und Spalten iterieren.

DECLARE @tblNm VARCHAR(MAX) 
DECLARE cTables CURSOR FOR 
    SELECT tblNm 
    FROM CompositeSchema 
    GROUP BY tblNm 
    ORDER BY tblNm 
OPEN cTables 
FETCH cTables INTO @tblNm 
WHILE @@FETCH_STATUS=0 
    BEGIN 
     PRINT 'Processing table '[email protected] 

     -- Start of code to execute for each table 

     DECLARE @sqlCreateTable VARCHAR(MAX) 
     SET @sqlCreateTable = 'CREATE TABLE ['[email protected]+'] (' 

     DECLARE @colNm VARCHAR(MAX),@colTyp VARCHAR(MAX),@colLen INT,@colReq BIT,@colWarning BIT,@colUni BIT,@colComUni BIT 
     DECLARE @isFirst BIT 
     SET @isFirst = 1 
     DECLARE cCols CURSOR FOR 
      SELECT colNm,colTyp,colLen,colReq,colWarning,colUni,colComUni 
      FROM CompositeSchema 
      WHERE [email protected] 
      ORDER BY colComUni DESC,colNm ASC 
     OPEN cCols 
     FETCH cCols INTO @colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni 
     WHILE @@FETCH_STATUS=0 
      BEGIN 
       PRINT 'Processing column ['[email protected]+'].['[email protected]+']' 

       -- Start of code to process each column (simplified!) 

       IF @isFirst=0 
        SET @sqlCreateTable = @sqlCreateTable+',' 
       SET @isFirst = 0 

       SET @sqlCreateTable = @sqlCreateTable+'['[email protected]+'] '[email protected] 
       IF NOT @colLen IS NULL 
        SET @sqlCreateTable = @sqlCreateTable+'('+CAST(@colLen AS VARCHAR)+')' 

       -- End of code to process each column 

       FETCH cCols INTO @colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni 
      END 
     CLOSE cCols 
     DEALLOCATE cCols 

     SET @sqlCreateTable = @sqlCreateTable+')' 
     PRINT @sqlCreateTable 

     -- EXEC(@sqlCreateTable) 

     -- End of code to execute for each table 

     FETCH cTables INTO @tblNm 
    END 
CLOSE cTables 
DEALLOCATE cTables 

Ein Cursor

In diesem Fall verwenden wir einen Cursor gerade. Wir verfolgen, was die aktuelle Tabelle ist, die wir in der Variablen @currentTblNm verarbeiten. Wenn sich die Variable ändert, erstellen wir alle Spalten gleichzeitig.

DECLARE @currentTblNm VARCHAR(MAX),@sqlCreateTable VARCHAR(MAX) 
SET @currentTblNm = '' 

DECLARE @tblNm VARCHAR(MAX),@colNm VARCHAR(MAX),@colTyp VARCHAR(MAX),@colLen INT,@colReq BIT,@colWarning BIT,@colUni BIT,@colComUni BIT 
DECLARE @isFirst BIT 
SET @isFirst = 1 
DECLARE cCols CURSOR FOR 
    SELECT tblNm,colNm,colTyp,colLen,colReq,colWarning,colUni,colComUni 
    FROM CompositeSchema 
    ORDER BY tblNm ASC,colComUni DESC,colNm ASC 
OPEN cCols 
FETCH cCols INTO @tblNm,@colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni 
WHILE @@FETCH_STATUS=0 
    BEGIN 
     IF @currentTblNm<>@tblNm 
      BEGIN 
       IF @sqlCreateTable<>'' 
        BEGIN 
         SET @sqlCreateTable = @sqlCreateTable+')' 
         PRINT @sqlCreateTable 
         --EXEC (@sqlCreateTable) 
        END 

       SET @isFirst = 1 
       SET @sqlCreateTable = 'CREATE TABLE ['[email protected]+'] (' 
       SET @currentTblNm = @tblNm 

       PRINT 'Processing table ['[email protected]+']' 
      END 

     -- Start of code to process each column (simplified!) 

     IF @isFirst=0 
      SET @sqlCreateTable = @sqlCreateTable+',' 
     SET @isFirst = 0 

     SET @sqlCreateTable = @sqlCreateTable+'['[email protected]+'] '[email protected] 
     IF NOT @colLen IS NULL 
      SET @sqlCreateTable = @sqlCreateTable+'('+CAST(@colLen AS VARCHAR)+')' 

     -- End of code to process each column 

     FETCH cCols INTO @tblNm,@colNm,@colTyp,@colLen,@colReq,@colWarning,@colUni,@colComUni 
    END 
CLOSE cCols 
DEALLOCATE cCols 

IF @sqlCreateTable<>'' 
    BEGIN 
     SET @sqlCreateTable = @sqlCreateTable+')' 
     PRINT @sqlCreateTable 

     -- EXEC(@sqlCreateTable) 
    END 

Beide Codeteile, zwei Cursor und ein Cursor sind vereinfacht. Die Logik, um alle Einschränkungen richtig zu erstellen (wie Primärschlüssel, eindeutige Einschränkungen, Fremdschlüssel usw.), die Logik, um die Spaltendatentypen richtig zuzuordnen, und nicht zu vergessen, die Unterscheidung zwischen dem Erstellen einer neuen Tabelle und dem Ändern einer existierende Tabelle würde den Rahmen dieses Beitrags sprengen.

Erwähnenswert ist, dass Sie auch deklarativen SQL-Code mit FOR XML verwenden können, um die Tabellenstruktur zu erstellen. Dies ist möglich und würde die CREATE TABLE-Anweisungen mit einer viel besseren Leistung generieren. Aus Erfahrung weiß ich, dass dieser Code viel schwieriger zu pflegen ist und Sie möglicherweise auf die Einschränkungen von deklarativem SQL stoßen.

+1

Vielen Dank! Ich fing tatsächlich an, einen Doppelcursor dafür zu bauen, als jemand in einem anderen Thread anfing, mir die xml-Version zu zeigen. Ich denke, die XML-Version wird besser sein, da viele Daten zu knacken sind. Aber wenn wir die Grenzen von SQL erreichen, kehre ich zurück zu diesem Thema. Vielen Dank! – MKasper