【问题标题】:Alter tables in a schema更改模式中的表
【发布时间】:2019-10-08 18:07:04
【问题描述】:

我正在尝试将默认值设置为列(Inserted_time),但首先我需要检查表中是否存在该列。如果该列不存在,我需要添加该列并给它一个默认值。 我正在使用 Sql Server Management Studio。 到目前为止,我已经编写了这段代码:

IF EXISTS ( select TABLE_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_CATALOG = 'DB_COPY' and COLUMN_NAME = 'Inserted_Time')
    begin
    ALTER TABLE table_name ADD CONSTRAINT [Inserted_Time_Def] SET DEFAULT (sysdatetimeoffset()) FOR [Inserted_Time]
    end

    else

    ALTER TABLE table_name ADD COLUMN [Inserted_Time] CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset()) WITH VALUES

一旦我检索到包含该列的表,我需要将该 table_name 添加到 Alter 命令。但我无法做到这一点。有人可以告诉我如何在 alter 语句中使用从 select 语句中检索到的 table_names 吗?

【问题讨论】:

  • 所以您想动态地执行此操作,并且针对每个表?如果列已经有约束怎么办?
  • 列没有那个约束。

标签: sql-server tsql ddl


【解决方案1】:

首先,您希望将所有表名放在一个临时表中,以便循环访问它。

之后,您可以使用游标对每个表名执行命令。

在我的示例中,我只打印了我想要执行的命令。这样您就可以确保代码首先执行您想要的操作。

例子:

select TABLE_NAME As TableName INTO #TablesList from INFORMATION_SCHEMA.COLUMNS where TABLE_CATALOG = 'DB_COPY' and COLUMN_NAME = 'Inserted_Time'

DECLARE @TablesCursor as CURSOR;
DECLARE @TableName as NVARCHAR(max);

DECLARE @CommandToExecute as NVARCHAR(max);

SET @TablesCursor = CURSOR FOR SELECT TableName FROM #TablesList;

OPEN @TablesCursor;
FETCH NEXT FROM @TablesCursor INTO @TableName;

WHILE @@FETCH_STATUS = 0
BEGIN

 SET @CommandToExecute = 'ALTER TABLE ' + @TableName + ' WHAT YOU WANNA DO '
 PRINT @CommandToExecute
 --EXEC(@CommandToExecute)

 FETCH NEXT FROM @TablesCursor INTO @TableName;

END

CLOSE @TablesCursor;
DEALLOCATE @TablesCursor;

【讨论】:

  • 这看起来不错,但是 EXEC(@CommandToExecute) 给出了以下错误:
  • 你把EXEC之前的那行改成什么了?
  • 我将 SET CommandToExecute 更改为 this = 'Select top (2) * from ' + @TableName + ';'
  • 您遇到的错误是什么?它对我有用
  • 我在那里犯了一个逻辑错误,我已经纠正了。谢谢您的帮助。成功了!!
【解决方案2】:

假设每个表都在不同的模式中,那么你可以这样做:

DECLARE @SQL nvarchar(MAX);
SET @SQL = STUFF((SELECT NCHAR(13) + NCHAR(10) +
                         CASE WHEN EXISTS (SELECT 1
                                           FROM INFORMATION_SCHEMA.COLUMNS C
                                           WHERE T.TABLE_SCHEMA = C.TABLE_SCHEMA
                                             AND T.TABLE_NAME = C.TABLE_SCHEMA
                                             AND C.COLUMN_NAME = N'Inserted_Time') THEN N'ALTER TABLE ' + QUOTENAME(T.TABLE_SCHEMA) + N'.' + QUOTENAME(T.TABLE_NAME) + N' ADD CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset()) FOR [Inserted_Time];'
                                                                                   ELSE N'ALTER TABLE ' + QUOTENAME(T.TABLE_SCHEMA) + N'.' + QUOTENAME(T.TABLE_NAME) + N' ADD COLUMN [Inserted_Time] CONSTRAINT [Inserted_Time_Def] DEFAULT (sysdatetimeoffset());'
                        END
                  FROM INFORMATION_SCHEMA.TABLES T
                  WHERE T.TABLE_CATALOG = N'DB_COPY'
                  FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,2,N'');

PRINT @SQL; --Your best friend. If more than 4,000 characters, use SELECT

EXECUTE sp_executesql @SQL;

如果您有大量架构,这很可能会大大优于 CURSOR 解决方案。

【讨论】:

  • 你能告诉我如何使用 select 来打印 @SQL 吗?输出有超过 4000 个字符。
  • @Larna :我在这里的目的是学习,所以如果我一两件事不知道也没关系。我认为更重要的是我愿意学习而不是仅仅因为我发现一些困难而放弃。无论如何,谢谢你的帮助。我很感激。
  • 您只需要替换PRINTSELECT @Jenna ... 选择变量的值就像选择列或函数或表达式的值一样。 (另外,最后是 u,而不是 a :))
猜你喜欢
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多