2017-01-25 3 views
-2

Ich versuche nur, Tabellen in Benutzerdatenbanken abgesehen von Systemdatenbanken zu erstellen.Schleife Skript funktioniert nicht

hier ist das Skript

Declare @V table (ID INT,name varchar(100)) 

DECLARE 
    @DatabaseName VARCHAR(50), 
    @SQL NVARCHAR(MAX) 
INSERT INTO @V(Id,name) 

select ROW_NUMBER()OVER(ORDER BY NAME), 
     name 
    from sys.databases 
      where database_id >= 5 

DECLARE @LoopCounter INT , @MaxId INT, 
     @Name NVARCHAR(100) 
SELECT @LoopCounter = min(id) , 
     @MaxId = max(Id) 
FROM @V 

WHILE(@LoopCounter IS NOT NULL 
     AND @LoopCounter <= @MaxId) 
BEGIN 
    SELECT @Name = Name 
    FROM @V WHERE Id = @LoopCounter 

    set @Name = @DatabaseName 

    SET @SQL = N'USE ' + QUOTENAME(@DatabaseName) 
+'CREATE TABLE T(ID INT)'; 


    SET @LoopCounter = @LoopCounter + 1 
    -- PRINT(@DatabaseName); 
    --PRINT(@SQL); 
    EXECUTE(@SQL) 
END 

warum ist es nicht Tabelle dynamisch erstellen?

wie nur Benutzerdatenbanken in unter Skript

statt

 DECLARE @Sql AS VARCHAR(4000) 
     SET @Sql = 'IF ''?'' NOT IN (''master'',''tempdb'',''model'',''msdb'',''ReportServer'',''ReportServerTempDB'') 
           EXECUTE ('' 

    USE [?] CREATE TABLE T (ID INT)'')' 
          EXEC sp_MSforeachdb 

@command1 = @Sql 
+0

Sie sollten dies stattdessen verwenden: [Eine zuverlässigere und flexiblere sp_MSforeachdb - Aaron Bertrand] (https://www.mssqltips.com/sqlservertip/2201/making-a-more-reliable-and-flexible-spmsforeachdb /) – SqlZim

+0

ja ich habe dieses Skript, aber müssen in diesem Loop scriiit @Aaron tun – mohan111

+1

Wird das nicht etwas wie 'USE MYDB1CREATE TABLE' erstellen? Anstelle aller Schleifenzähler usw. können Sie auch einfach den Cursor verwenden. –

Antwort

1

Die Probleme mit Ihrem Skript sind hier manuell geben zu bekommen:

WHILE(@LoopCounter IS NOT NULL 
     AND @LoopCounter <= @MaxId) 
BEGIN 
    SELECT @Name = Name 
    FROM @V WHERE Id = @LoopCounter 

    --set @Name = @DatabaseName -- this will assign value from @DatabaseName into @Name, but you should do the vice versa: 

    set @DatabaseName = @Name 

    SET @SQL = N'USE ' + QUOTENAME(@DatabaseName) 
+' CREATE TABLE T(ID INT)'; -- I would also add space here, it might work with [XXX]create table 


    SET @LoopCounter = @LoopCounter + 1 
    -- PRINT(@DatabaseName); 
    --PRINT(@SQL); 
    EXECUTE(@SQL) 
END 

Da @DatabaseName null war, die Das Ergebnis von @SQL war null, und die Ausführung von null ist wahrscheinlich nur in Ordnung.

+0

haha ​​schlug mich dazu –

1

Ihr Entwurf der Version mit der sp_MSforeachdb Prozedur war auch in Ordnung; Sie haben nach einer Version gefragt, ohne die Namen der Systemdatenbanken zu schreiben. Leider wurde dies immer noch nicht implementiert - es gibt kein zuverlässiges Flag oder eine Eigenschaft in einer Datenbank, die es eindeutig als Benutzerdatenbank identifizieren würde. Microsoft selbst die (invertiert) Kriterien anwenden ich unten bin mit, wenn sie den Inhalt der „Systemdatenbank“ -Ordner in SSMS Liste ... siehe auch hier: https://stackoverflow.com/a/28590305/1132334

SELECT 
    [name] 
FROM sys.databases 
WHERE CAST(CASE WHEN [name] IN ('master','model','msdb','tempdb') THEN 1 ELSE is_distributor END AS bit)=0 

Hier ist ein Skript getestet:

DECLARE @sql varchar(max) 

SET @sql='IF ''?'' IN (SELECT [name] FROM sys.databases WHERE CAST(CASE WHEN [name] IN (''master'',''model'',''msdb'',''tempdb'') THEN 1 ELSE is_distributor END AS bit)=0) 
    EXECUTE (''USE [?] CREATE TABLE T (ID int)'')' 

EXEC sp_MSforeachdb @command1 = @Sql 
+0

vielen Dank sehr hilfreich – mohan111