使一个表等于另一个没有删除*

时间:2010-06-11 00:35:26

标签: sql-server delete-row

我知道这有点奇怪但是如果有人有任何帮助会非常感激。

场景是我们在远程站点有一个生产数据库,在我们的本地办公室有一个开发人员数据库。开发人员直接对开发人员数据库进行更改,作为部署过程的一部分,C#应用程序运行并生成一系列.sql脚本,我们可以在远程端执行(本质上是删除*,插入)但我们正在寻找一些东西更精细,因为删除*的停机时间是不可接受的。这是控制主要网站的菜单项,功能等的所有参考数据。

我有一个sproc,基本上返回两个表的差异。我的想法是,我可以将所有预期的数据插入到tmp表中,执行diff,并从目标表中删除任何不在源代码中的内容,然后将其他所有内容都插入。

问题是,如果不使用游标,有一种简单的方法吗?为了说明sproc,返回一个如下结构的记录集:

TableName Col1 Col2 Col3 目的地 SRC

记录集中TableName = Dest的任何内容都应该被删除(因为它在src中不存在),并且Src中的任何内容都应该被插入到dest中。我想不出一种方法来做这个纯粹的基础设置,但我的DB-fu很弱。

任何帮助将不胜感激。如果解释是粗略的,请道歉;如果您需要更多细节,请告诉我。

4 个答案:

答案 0 :(得分:3)

是的,那个sproc会起作用。对该表使用FULL JOIN并添加一列以指示插入,更新或删除。然后根据列指示符为它们创建单独的SQL语句。基于设置。


抱歉不是一个完整的加入,你需要将它们分解为左边和右边的连接。在NotePad中这样做了,如果不起作用,请道歉:

INSERT INTO tempDeployData(ID,IUDType)
SELECT ed.id, 'D'
FROM    tmpDeployData td
    RIGHT JOIN existingData ed ON td.id = ed.id
WHERE td.id IS NULL     


UPDATE td
SET td.IUDType = CASE WHEN ed.id IS NULL THEN
                         'I'
                         ELSE
                         'U'
                         END
FROM    tmpDeployData td
    LEFT JOIN existingData ed ON td.id = ed.id


INSERT INTO existingData(ID,a,b,c)
SELECT td.ID,td.a,td.b,td.c
FROM tmpDeployData td
WHERE td.IUDType = 'I'

DELETE ed
FROM existingData ed
    INNER JOIN tmpDeployData td ON ed.ID = td.ID
WHERE td.IUDType = 'D'

UPDATE  ed
SET     ed.a = td.a,
        ed.b = td.b,
        ed.c = td.c
FROM existingData ed
INNER JOIN tmpDeployData td ON ed.ID = td.ID
WHERE td.IUDType = 'U' 

刚刚意识到你将信息作为临时表提取到临时表中,而不是数据来源。在这种情况下,您可以使用FULL JOIN:

INSERT INTO tmpDeployData(ID,a,b,c,IUDType)
SELECT  sd.ID, 
        sd.a, 
        sd.b, 
        sd.c
        'IUDType' = CASE WHEN ed.id IS NULL THEN
                         'I'
                         WHEN sd.id IS NULL THEN
                         'D'
                         ELSE
                         'U'
                         END
FROM    sourceData sd
    FULL JOIN existingData ed ON sd.id = ed.id

然后是和以前一样的DML语句。

答案 1 :(得分:1)

假设您正在使用SQL Server 2008,那么有一种更简单的方法可以做到这一点:MERGE语句。

将所有更改从一个表迁移到另一个表非常简单:

MERGE DestinationTable d
USING SourceTable s
    ON d.Id = s.Id
WHEN MATCHED THEN UPDATE
    SET d.Col1 = s.Col1, d.Col2 = s.Col2, ...
WHEN NOT MATCHED BY TARGET THEN
    INSERT (Id, Col1, Col2, ...)
    VALUES (s.Id, s.Col1, s.Col2, ...)
WHEN NOT MATCHED BY SOURCE THEN
    DELETE;

就是这样。在此之后,DestinationTable将与SourceTable相同。

答案 2 :(得分:1)

点击tablediff

表不需要参与复制来运行该实用程序。有一个很好的-f开关来生成t-sql以使表'同步':

  

生成Transact-SQL脚本   把桌子带到目的地   服务器与表融合   在源服务器上。您可以   可选择指定名称和路径   生成的Transact-SQL脚本   文件。如果未指定file_name,   Transact-SQL脚本文件是   在目录中生成的   实用程序运行。

答案 3 :(得分:0)

为什么不直接备份生产数据库并将其恢复到开发数据库中?您应该在生成数据库中具有可以在还原后在数据库上运行的所有ddl差异的更改脚本,并且它将测试部署到生产。

编辑: 抱歉,只需重新阅读您的问题,看起来您正在将配置信息存储在开发数据库中并从中生成更改脚本,这样就无法解决问题了。

我建议手动创建更改脚本并将它们存储在源代码管理中。然后使用sqlcmd或osql以及批处理文件在数据库上运行更改脚本。