循环脚本不起作用

时间:2017-01-25 18:43:10

标签: sql sql-server tsql

我只是尝试在除系统数据库之外的用户数据库中创建表。

这是脚本

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

为什么不动态创建表?

如何在下面的脚本中仅获取用户数据库

而不是手动提供

     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

2 个答案:

答案 0 :(得分:1)

您的脚本存在问题:

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

因为@DatabaseName为null,所以@SQL的结果为null,并且执行null很可能就好了。

答案 1 :(得分:1)

您使用sp_MSforeachdb程序的版本草稿也没问题;你没有写出系统数据库名称就问了一个版本。遗憾的是,这仍未实现 - 数据库上没有可靠的标志或属性可以清楚地将其标识为用户数据库。当他们列出&#34;系统数据库&#34;的内容时,微软自己应用我在下面使用的(反向)标准。 SSMS中的文件夹...另见: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

这是一个经过测试的脚本:

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