【问题标题】:SQL Server delete all tables under special schema with temporal tablesSQL Server 删除具有临时表的特殊架构下的所有表
【发布时间】:2021-04-22 22:06:30
【问题描述】:

我正在尝试删除带有临时表的数据库方案。 没有通过谷歌搜索找到的现有脚本,支持时态表。

有人已经这样做了吗?

该方案中有许多时态表,其中包含许多具有依赖关系的约束。因此,当我尝试放弃该方案时,它会抱怨依赖关系。 基本上我正在寻找一个存储过程或遍历所有数据库对象并一个一个删除的东西。

创建示例表的脚本

USE [master];
GO

CREATE DATABASE [TestDb];
GO

USE [TestDb];
GO

CREATE SCHEMA [TestScheme];
GO

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

CREATE TABLE [TestScheme].[Country]
(
    [CountryCode] [char](2) NOT NULL, 
    [Country] [varchar](60) NOT NULL, 
    [ValidFrom] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL, 
    [ValidTo] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL, 

    CONSTRAINT [PK_TestScheme_Country_CountryCode] 
        PRIMARY KEY CLUSTERED([CountryCode] ASC) 
                WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 95) ON [PRIMARY], 
    PERIOD FOR SYSTEM_TIME([ValidFrom], [ValidTo])
) ON [PRIMARY] 
     WITH (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [TestScheme].[CountryHistory]));
GO

SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO

CREATE TABLE [TestScheme].[Address]
(
     [AddressId] [int] IDENTITY(1, 1) NOT NULL, 
     [City] [varchar](100) NOT NULL, 
     [CountryCode] [char](2) NOT NULL, 
     [ValidFrom] [datetime2](7) GENERATED ALWAYS AS ROW START NOT NULL, 
     [ValidTo] [datetime2](7) GENERATED ALWAYS AS ROW END NOT NULL, 

     CONSTRAINT [PK_TestScheme_Address_AddressId] 
         PRIMARY KEY CLUSTERED([AddressId] ASC) 
                 WITH (PAD_INDEX = ON, STATISTICS_NORECOMPUTE = OFF, 
                       IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                       ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY], 
     PERIOD FOR SYSTEM_TIME([ValidFrom], [ValidTo])
)
ON [PRIMARY] 
   WITH (SYSTEM_VERSIONING = ON(HISTORY_TABLE = [TestScheme].[AddressHistory]));
GO

ALTER TABLE [TestScheme].[Address] WITH CHECK
    ADD CONSTRAINT [FK_TestScheme_CountryCode] 
        FOREIGN KEY([CountryCode]) REFERENCES [TestScheme].[Country]([CountryCode]);
GO

ALTER TABLE [TestScheme].[Address] CHECK CONSTRAINT [FK_TestScheme_CountryCode];
GO

查询删除方案:

USE [TestDb];
GO

DROP SCHEMA [TestScheme];
GO

查询删除表:

USE [TestDb]
GO

ALTER TABLE [TestScheme].[Country] SET (SYSTEM_VERSIONING = OFF)
GO

IF EXISTS (SELECT * FROM sys.objects 
           WHERE object_id = OBJECT_ID(N'[TestScheme].[Country]') AND type in (N'U'))
    DROP TABLE [TestScheme].[Country]
GO

IF EXISTS (SELECT * FROM sys.objects 
           WHERE object_id = OBJECT_ID(N'[TestScheme].[CountryHistory]') AND type in (N'U'))
    DROP TABLE [TestScheme].[CountryHistory]
GO

所以问题是有很多数据库对象,我真的不想创建一个巨大的脚本来一一删除。

谢谢!

【问题讨论】:

  • 请添加一个示例来说明您的意思 - 您不能删除启用了系统版本控制的表。
  • 希望这个描述已经足够了,我现在已经在创建一个脚本,如果它运行良好会上传它,谢谢!
  • 您绝对可以简化代码以删除表以使用DROP TABLE IF EXISTS xyz; 并避免所有检查sys.objects .. see more about DROP IF EXISTS

标签: sql-server database temporal-tables


【解决方案1】:

谢谢大家,以下是我创建的脚本,它对我有用。

USE TestDb;
GO
DECLARE @SchemeName varchar(50)= 'TestScheme';
DECLARE @DatabaseName varchar(50)= 'TestDb';
DECLARE @sql nvarchar(max)= '';

/*Removing versioning on temporal tables*/
WITH selectedTables
     AS (SELECT concat('[', @DatabaseName, '].[', @SchemeName, '].[', name, ']') AS TableName
         FROM SYS.TABLES    WHERE history_table_id IS NOT NULL AND  SCHEMA_NAME(schema_id) = @SchemeName)
     SELECT @sql = COALESCE(@sql, N'') + 'ALTER TABLE   ' + TableName + '   SET ( SYSTEM_VERSIONING = OFF  );'
     FROM selectedTables;

SELECT @sql;
EXEC sp_executesql @sql;

/*Remove constraints*/
SET @sql = N'';
SELECT @sql = COALESCE(@sql, N'') + N'ALTER TABLE ' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name) + N' DROP CONSTRAINT ' + QUOTENAME(c.name) + ';'
FROM SYS.OBJECTS AS c   INNER JOIN  SYS.TABLES AS t ON c.parent_object_id = t.[object_id]
     INNER JOIN SYS.SCHEMAS AS s    ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN( 'D', 'C', 'F', 'PK', 'UQ' ) AND  s.name = @SchemeName
ORDER BY c.[type];

SELECT @sql;
EXEC sp_executesql @sql;

/*Delete Tables*/
SET @sql = N'';
SELECT @sql =   COALESCE(@sql, N'') + N'DROP TABLE ['+@SchemeName+'].' + QUOTENAME(TABLE_NAME) + N';' + CHAR(13)
FROM INFORMATION_SCHEMA.TABLES  WHERE TABLE_SCHEMA = @SchemeName    AND TABLE_TYPE = 'BASE TABLE';

SELECT @sql
EXEC sp_executesql @sql;

/*Drop scheme*/
SET @sql = N'';
SELECT @sql =   COALESCE(@sql, N'') + N'DROP SCHEMA IF EXISTS ' + @SchemeName + ';' + CHAR(13);

SELECT @sql
EXEC sp_executesql @sql;
GO

再次感谢!

【讨论】:

    最近更新 更多