按照外键引用的表的顺序将数据从 PROD 重新加载到非 PROD

问题描述 投票:0回答:1

有没有动态脚本可以

  1. 按顺序截断多个表
  2. 使用链接服务器从另一台服务器加载数据,
  3. 注意重新加载顺序,以免出现任何外键引用错误, 理想的顺序: a) 删除 FK, b) 截断表, c) 重新加载数据,
    (i) 将身份插入设置为 (二) 插入数据 (iii) 将身份插入设置为关闭
    d) 创建外键
  4. 能够识别数据库表、约束和键,而无需将其作为用户的输入。
sql-server
1个回答
0
投票

最近我生成了以下脚本,它帮助我将数据从生产环境重新加载(改造)到非生产环境:

DECLARE @linkedServerName NVARCHAR(255) = 'ProductionLinkedServer'
DECLARE @DatabaseName NVARCHAR(255) = 'DeliveryPromiseGlobal'
DECLARE @Schema NVARCHAR(255) = 'dbo'

DECLARE @DropForeignKeyTemplate NVARCHAR(MAX) = 'ALTER TABLE %s DROP CONSTRAINT %s;';
DECLARE @CreateForeignKeyTemplate NVARCHAR(MAX) = 'ALTER TABLE %s WITH CHECK ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);';
DECLARE @TruncateTemplate NVARCHAR(MAX) = 'TRUNCATE TABLE %s;';
DECLARE @InsertDataTemplate NVARCHAR(MAX) = 'SET IDENTITY_INSERT %s ON; INSERT INTO %s SELECT * FROM %s.%s.%s.%s; SET IDENTITY_INSERT %s OFF;';

DECLARE @DprTables TABLE (
TableName NVARCHAR(MAX),
ForeignKeyTableName NVARCHAR(MAX),
ForeignKeyConstraintName NVARCHAR(MAX),
DropForeignKeyScript NVARCHAR(MAX),
CreateForeignKeyScript NVARCHAR(MAX),
TruncateScript NVARCHAR(MAX),
HasForeignKey BIT,
InsertDataScript NVARCHAR(MAX) -- New column for insert data script
);

INSERT INTO @DprTables (TableName, ForeignKeyTableName, ForeignKeyConstraintName, DropForeignKeyScript, CreateForeignKeyScript, TruncateScript, HasForeignKey, InsertDataScript)
SELECT t.name AS TableName,
   OBJECT_NAME(fk.referenced_object_id) AS ForeignKeyTableName,
   fk.name AS ForeignKeyConstraintName,
   IIF(fk.name is not null, FORMATMESSAGE(@DropForeignKeyTemplate, QUOTENAME(t.name),QUOTENAME(fk.name)),'') AS DropForeignKeyScript,
   IIF(fk.name IS NOT NULL, FORMATMESSAGE(@CreateForeignKeyTemplate,QUOTENAME(t.name),QUOTENAME(fk.name),STRING_AGG(QUOTENAME(c.COLUMN_NAME), ', ') WITHIN GROUP (ORDER BY ic.ORDINAL_POSITION) ,QUOTENAME(OBJECT_NAME(fk.referenced_object_id)),STRING_AGG(QUOTENAME(c.COLUMN_NAME), ', ') 
WITHIN GROUP (ORDER BY ic.ORDINAL_POSITION)), 
       ''
      ) AS CreateForeignKeyScript,
FORMATMESSAGE(@TruncateTemplate, QUOTENAME(t.name)) AS TruncateScript,
   IIF(fk.name IS NOT NULL, 1, 0) AS HasForeignKey,
   FORMATMESSAGE(@InsertDataTemplate, 
              QUOTENAME(t.name), 
              QUOTENAME(t.name), 
              QUOTENAME(@linkedServerName), 
              QUOTENAME(@DatabaseName), 
              QUOTENAME(@Schema), 
              QUOTENAME(t.name),
              QUOTENAME(t.name)) AS InsertDataScript -- Insert data script from linked server
FROM sys.tables t
LEFT JOIN sys.foreign_keys fk ON fk.parent_object_id = t.object_id
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE AS ic ON fk.name = ic.CONSTRAINT_NAME
LEFT JOIN INFORMATION_SCHEMA.COLUMNS AS c ON ic.TABLE_NAME = c.TABLE_NAME AND ic.COLUMN_NAME = c.COLUMN_NAME
where isnull(fk.name,'') <> 'FK_DprAdvanceScoring_RuleId'
GROUP BY t.name, fk.name, fk.referenced_object_id
ORDER BY fk.name DESC, t.name;

--CREATE LINKED SERVER IF NOT ALREADY EXISTS
-- Check if the linked server already exists
DECLARE @existingLinkedServer NVARCHAR(255)

SELECT @existingLinkedServer = name
FROM sys.servers
WHERE name = @linkedServerName

IF @existingLinkedServer IS NULL
BEGIN
    EXEC sp_addlinkedserver   
       @server = @linkedServerName, -- Name of the linked server
       @srvproduct = '',  
       @provider = 'SQLNCLI', -- Provider for SQL Server
       @datasrc = 'serveraddress,port', -- IP address and port of the server
       @provstr = 'UID=userId;PWD=password'; -- SQL Server authentication credentials

    PRINT 'Linked server created successfully.'
END
ELSE
BEGIN
    PRINT 'Linked server already exists.'
END

--执行脚本 声明 @SqlCommand NVARCHAR(MAX); DECLARE @Commands TABLE(命令 NVARCHAR(MAX));

-- Populate the @Commands table with all commands
INSERT INTO @Commands (Command)
SELECT DropForeignKeyScript FROM @DprTables where DropForeignKeyScript <> '' GROUP BY DropForeignKeyScript 
UNION ALL
SELECT TruncateScript FROM @DprTables where TruncateScript <> '' GROUP BY TruncateScript 
UNION ALL
SELECT InsertDataScript FROM @DprTables where InsertDataScript <> '' GROUP BY InsertDataScript
UNION ALL
SELECT CreateForeignKeyScript FROM @DprTables where CreateForeignKeyScript <> '' GROUP BY CreateForeignKeyScript 

-- Initialize loop variables
DECLARE @RowCount INT = (SELECT COUNT(*) FROM @Commands)
DECLARE @Counter INT = 1

--SELECT * FROM @COMMANDS
    
-- Loop through each command and execute it
WHILE @Counter <= @RowCount
BEGIN
    SELECT @SqlCommand = Command
    FROM @Commands
    WHERE (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) = @Counter
    -- Execute the command
    EXEC sp_executesql @SqlCommand
    SET @Counter = @Counter + 1
END
© www.soinside.com 2019 - 2024. All rights reserved.