3

我知道这有点奇怪,但如果有人有任何帮助,将不胜感激。

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

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

问题是有没有一种简单的方法可以在不使用光标的情况下做到这一点?为了说明 sproc 返回一个结构如下的记录集:

表名 Col1 Col2 Col3 Dest Src

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

任何帮助,将不胜感激。如果解释粗略,请致歉;如果您需要更多详细信息,请告诉我。

4

4 回答 4

3

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


抱歉不是 FULL JOIN,您需要将它们分解为单独的 LEFT 和 RIGHT JOIN。在记事本中做了这个,如果它不起作用,请道歉:

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 语句。

于 2010-06-11T00:44:24.207 回答
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之后相同。

于 2010-06-11T01:30:59.807 回答
1

参加tablediff

表不需要参与复制即可运行该实用程序。有一个很棒的 -f 开关可以生成 t-sql 以将表“同步”:

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

于 2010-06-11T01:42:47.650 回答
0

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

编辑:对不起,只是重新阅读您的问题,看起来您将配置信息存储在开发数据库中并从中生成更改脚本,因此这不起作用。

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

于 2010-06-11T21:54:33.720 回答