用另一个表中的数据覆盖表 - SQL

Riz*_*wan 10 sql-server

我们的用户想要从生产中刷新 QA 数据库,但想要两个表(我们称它们为 T1 和 T2)来保留原始 QA 数据。因此,我将两个表从 QA (DB1) 复制到临时 QA 数据库 (DB2)。然后从生产中刷新 DB1。刷新后,我想将 T1 和 T2 数据从 DB2 覆盖到 DB1,以便它可以包含预刷新 QA 值。

我做了以下工作:

  1. select * 
    INTO D1.dbo.T1
    FROM D2.dbo.T1
    
    Run Code Online (Sandbox Code Playgroud)
  2. 然后从 prod 刷新 D1

  3. 然后使用以下步骤截断 T1:

    SELECT COUNT(*) AS BeforeTruncateCount
    FROM T1;
    GO
    TRUNCATE TABLE T1;
    GO
    SELECT COUNT(*) AS AfterTruncateCount
    FROM T1;
    GO
    
    Run Code Online (Sandbox Code Playgroud)
  4. 现在,当我返回将数据从 D2.T1 复制到 D1.T1 时,我收到错误消息,即数据库中已存在名为 T1 的对象。

我应该放下桌子并复制吗?

或者整个过程有没有更好的方法?

Kin*_*hah 7

最好是使用 SSIS(数据导入/导出)来做到这一点。它具有将选定表从源传输到目标的功能。或者,您甚至可以保存包,以便将来/重复传输时可以重复使用。

编辑:为清晰起见,添加更多屏幕截图。

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明


Ken*_*her 7

结合@Kin 和@DavidSpillett 的答案。

首先是一个假设。DB1 和 DB2 在同一个实例上。听起来确实如此,但说出显而易见的事情并没有什么坏处(尤其是因为我之前认为很明显的事情我错了。)

鉴于此,如果数据很大,比如数百万行,则使用 SSIS 包。这具有您想要使用的一项特定功能。您可以指定批量大小。这样你的交易规模会更小。SSIS 包的缺点是它给您的过程增加了一定程度的复杂性。它不是很大,但是如果您使用较小的桌子,则不需要它。

这将我们引向另一种选择。但是,如果数据在几十万或更小的范围内,则使用这样的代码。

USE D1;
GO
TRUNCATE TABLE dbo.T1;
GO
INSERT INTO D1.dbo.T1
SELECT * 
FROM D2.dbo.T1;
GO
Run Code Online (Sandbox Code Playgroud)

最后但并非最不重要的是,如果它在寄宿生的某个地方,那么我会尝试两者,看看哪种最适合您。

注意:您也可以考虑不使用SELECT *INSERT INTO,而是指定一个字段列表。

这种结构看起来像这样

INSERT INTO D1.dbo.T1 (Field1, Field2)
SELECT Field1, Field2
FROM D2.dbo.T1;
Run Code Online (Sandbox Code Playgroud)


Dav*_*ett 6

使用SELECT <stuff> INTO <target> FROM ...SQL Server 语法的IIRC始终假定您要从头开始创建目标表。当表已经存在时,请尝试INSERT <target> SELECT <stuff> FROM ...

  • 此外,在将数据移回 D1 时,David 的答案也比 DROP 和 SELECT INTO 更好,因为如果删除 D1 表,您将丢失任何子对象(即外键、主键、触发器等)。 ) (5认同)
  • 我同意@Delux。您将失去的另一件重要事情是显式权限。如果用户具有特定于该表的权限(而不是说`db_datareader`),那么如果您删除该表,那么您将失去这些权限。 (2认同)