【问题标题】:Mirroring Table Modifications镜像表修改
【发布时间】:2010-09-19 13:58:12
【问题描述】:

我有一组用于跟踪账单的表格。这些表是从每周运行的 SSIS 进程加载的。

我正在创建第二组表格,以跟踪对通过网络进行的账单的调整。我们的一些客户亲手填写他们的账单,所有这些条目都需要定期备份(SSIS 馈送的数据总是可以再次导入,因此不会备份)。

这种行为有最佳实践吗?我正在考虑实现一个 DDL 触发器,该触发器将解析 ALTER TABLE 调用并更改被调用的表。这有点痛苦,我很好奇是否有更好的方法。

【问题讨论】:

    标签: sql sql-server database sql-server-2005 database-design


    【解决方案1】:

    我个人会将 SSIS 馈送表放在一个数据库中(设置为简单恢复模式),而将其他表放在同一服务器上的单独数据库中,该服务器设置为完全恢复模式。然后我会定期在第二个数据库上设置备份。一个典型的备份计划是每周一次完整备份,每晚备份一次,每 15-30 分钟进行一次事务备份,具体取决于输入的数据量。)请务必定期测试恢复备份,并在客户需要时学习如何执行此操作因为数据库已关闭而尖叫;这是一件好事。

    【讨论】:

      【解决方案2】:

      我最终使用 DDL 触发器将更改从一个表复制到另一个表。唯一的问题是,如果表或列名包含保留字的一部分 - VARCHAR 的 ARCH - 这将导致修改脚本出现问题。

      再次感谢 Brent Ozar 在我 blogged them 之前检查我的想法时出错。

      -- Create pvt and pvtWeb as test tables
      CREATE TABLE [dbo].[pvt](
         [VendorID] [int] NULL,
         [Emp1] [int] NULL,
         [Emp2] [int] NULL,
         [Emp3] [int] NULL,
         [Emp4] [int] NULL,
         [Emp5] [int] NULL
      ) ON [PRIMARY];
      GO
      
      
      CREATE TABLE [dbo].[pvtWeb](
         [VendorID] [int] NULL,
         [Emp1] [int] NULL,
         [Emp2] [int] NULL,
         [Emp3] [int] NULL,
         [Emp4] [int] NULL,
         [Emp5] [int] NULL
      ) ON [PRIMARY];
      GO
      
      
      IF EXISTS(SELECT * FROM sys.triggers WHERE name = ‘ddl_trigger_pvt_alter’)
         DROP TRIGGER ddl_trigger_pvt_alter ON DATABASE;
      GO
      
      -- Create a trigger that will trap ALTER TABLE events
      CREATE TRIGGER ddl_trigger_pvt_alter
      ON DATABASE
      FOR ALTER_TABLE
      AS
         DECLARE @data XML;
         DECLARE @tableName NVARCHAR(255);
         DECLARE @newTableName NVARCHAR(255);
         DECLARE @sql NVARCHAR(MAX);
      
         SET @sql = ”;
         -- Store the event in an XML variable
         SET @data = EVENTDATA();
      
         -- Get the name of the table that is being modified
         SELECT @tableName = @data.value(‘(/EVENT_INSTANCE/ObjectName)[1]‘, ‘NVARCHAR(255)’);
         -- Get the actual SQL that was executed
         SELECT @sql = @data.value(‘(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]‘, ‘NVARCHAR(MAX)’);
      
         -- Figure out the name of the new table
         SET @newTableName = @tableName + ‘Web’;
      
         -- Replace the original table name with the new table name
         -- str_replace is from Robyn Page and Phil Factor’s delighful post on 
         -- string arrays in SQL. The other posts on string functions are indispensible
         -- to handling string input
         --
         -- http://www.simple-talk.com/sql/t-sql-programming/tsql-string-array-workbench/
         -- http://www.simple-talk.com/sql/t-sql-programming/sql-string-user-function-workbench-part-1/
         --http://www.simple-talk.com/sql/t-sql-programming/sql-string-user-function-workbench-part-2/
         SET @sql = dbo.str_replace(@tableName, @newTableName, @sql);
      
         -- Debug the SQL if needed.
         --PRINT @sql;
      
         IF OBJECT_ID(@newTableName, N’U’) IS NOT NULL
         BEGIN
             BEGIN TRY
                 -- Now that the table name has been changed, execute the new SQL
                 EXEC sp_executesql @sql;
             END TRY
             BEGIN CATCH
                 -- Rollback any existing transactions and report the full nasty 
                 -- error back to the user.
                 IF @@TRANCOUNT > 0
                     ROLLBACK TRANSACTION;
      
                 DECLARE
                     @ERROR_SEVERITY INT,
                     @ERROR_STATE    INT,
                     @ERROR_NUMBER   INT,
                     @ERROR_LINE     INT,
                     @ERROR_MESSAGE  NVARCHAR(4000);
      
                 SELECT
                     @ERROR_SEVERITY = ERROR_SEVERITY(),
                     @ERROR_STATE    = ERROR_STATE(),
                     @ERROR_NUMBER   = ERROR_NUMBER(),
                     @ERROR_LINE     = ERROR_LINE(),
                     @ERROR_MESSAGE  = ERROR_MESSAGE();
      
                 RAISERROR(‘Msg %d, Line %d, :%s’,
                     @ERROR_SEVERITY,
                     @ERROR_STATE,
                     @ERROR_NUMBER,
                     @ERROR_LINE,
                     @ERROR_MESSAGE);
             END CATCH
         END
      GO
      
      
      
      
      ALTER TABLE pvt
      ADD test INT NULL;
      GO
      
      EXEC sp_help pvt;
      GO
      
      ALTER TABLE pvt
      DROP COLUMN test;
      GO
      
      EXEC sp_help pvt;
      GO
      

      【讨论】:

        猜你喜欢
        • 2017-09-10
        • 1970-01-01
        • 1970-01-01
        • 2014-12-03
        • 2021-12-02
        • 2019-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多