【问题标题】:How to merge two databases on two different servers?如何合并两个不同服务器上的两个数据库?
【发布时间】:2015-06-16 18:48:26
【问题描述】:

我有两个不同的数据库,客户端一个从.MDF 文件附加到.\SQLEXPRESS 服务器。主服务器在另一台名为COMPUTER_NAME 的计算机上的服务器上运行。

我想使用 C# 合并这些以运行 .SQL 文件。我将在下面粘贴我的代码以供参考,但基本上我的问题是,如果我使用

连接到服务器
 string sqlConnectionString = @"Server=.\SQLEXPRESS; Trusted_Connection=True";

然后我在COMPUTER_NAME 上找不到数据库。如果我使用

 string sqlConnectionString = @"Server=COMPUTER_NAME; Trusted_Connection=True";

它将在 COMPUTER_NAME 的 C: 驱动器上查找我的 .MDF 文件,而不是本地计算机。

如何连接到不同服务器上的这两个数据库?

其他信息:

我正在使用的 SQL 脚本。当两个数据库都在同一台服务器上时,这可以完美地恢复,但我不能再这样做了。

CREATE DATABASE ClientDB  
ON (Filename = 'C:\Clayton.mdf')
   , (Filename = 'C:\Clayton_log.ldf') 
FOR ATTACH;

-- update the client from the master 
MERGE [ClientDB].[dbo].[table] trgt
using [MasterDB].[dbo].[table] src
ON trgt.id = src.id 

WHEN matched AND trgt.lastmodified <= src.lastmodified THEN -- if master row is newer 
   UPDATE SET trgt.[info] = src.[info], ...                 -- update the client 

WHEN NOT matched BY source                                  -- delete rows added by client 
   THEN DELETE 

WHEN NOT matched BY target                                  -- insert rows added by master 
   THEN INSERT ( [info], ... ) VALUES (src.[info], ... ); 


-- close all connections to database
ALTER DATABASE ClientDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE; 

-- detach database
EXEC sp_detach_db 'ClientDB', 'true'; 

我使用 C# 运行它,如下所示:

 string sqlConnectionString = @"Server=.\SQLEXPRESS; Trusted_Connection=True";

 string script = File.ReadAllText(Environment.CurrentDirectory + @"\MergeTotal.sql");
 SqlConnection conn = new SqlConnection(sqlConnectionString);

 IEnumerable<string> commandStrings = Regex.Split(script, @"^\s*GO\s*$",
                            RegexOptions.Multiline | RegexOptions.IgnoreCase);

 conn.Open();
 foreach (string commandString in commandStrings)
 {
     if (commandString.Trim() != "")
     {
         using (var command = new SqlCommand(commandString, conn))
         {
             command.ExecuteNonQuery();
         }
     }
 }

我不在乎整个过程是发生在.SQL 还是C#,只要它具有预期的效果即可。

提前感谢您提供任何指导或建议。

【问题讨论】:

  • 你需要多久运行一次?
  • 我经常害怕。现在它的配置是每次程序启动时,它都会检查它是否与主数据库连接到网络,如果是则合并。
  • 你可能不得不考虑重新设计它的工作方式,因为你不能像那样真正合并。您可能应该跟踪更改,然后在主服务器上重新制定它们。
  • 就我的目的而言,这并不是一个真正可行的选择。必须有某种方法来编写两个数据库的脚本。我在玩sp_addlinkedserver,我认为我在正确的轨道上。
  • 所以在无所事事之后发现you can't use a merge on linked servers,所以我又回到了我开始的地方......

标签: sql sql-server connection-string sql-server-express


【解决方案1】:

如果需要,链接服务器将帮助您能够同时访问数据。但是,如果您希望将数据合并在一起,我建议您查看sp_generate_merge 以将数据拉入合并脚本中(对于移动数据非常方便)。另请参阅我关于生成合并数据的问题here

【讨论】:

  • 感谢您的回复!你能举个例子说明在这种情况下我将如何使用它吗?我需要合并两种方式来提交两个版本的更改,但我不断收到错误the target of a MERGE statement cannot be a remote table
  • 您需要在一台机器上生成合并脚本,复制输出,然后在另一台机器上运行合并。然后你会扭转这个过程。
【解决方案2】:

好吧,我不得不完全扔掉整个 .MDF 的东西。我没有从.MDF 附加和重新附加数据库,而是设置了数据库。

这是我在平板电脑上初始化本地数据库的代码:

CREATE DATABASE LocalClaytonDB  
ON (Filename = 'C:\ProgramData\Clayton\Clayton.mdf')
   , (Filename = 'C:\ProgramData\Clayton\Clayton_log.ldf') 
FOR ATTACH;
GO

EXEC sp_addlinkedserver @server='Server'

这是我同步两个数据库的代码:

-- update the client from the master 
MERGE [LocalClaytonDB].[dbo].[tableName] trgt
using [Server].[Clayton].[dbo].[tableName] src

ON trgt.id = src.id 

WHEN matched AND trgt.lastmodified <= src.lastmodified THEN 
  -- if the master has a row newer than the client
  -- update the client                       
  UPDATE SET trgt.[allColumns]      = src.[allColumns],
             trgt.[id]              = src.[id], 
             trgt.[lastmodified]    = src.[lastmodified] 

-- delete any rows added by a client 
WHEN NOT matched BY source 
THEN 
  DELETE 

-- insert any rows added by the master 
WHEN NOT matched BY target 
THEN 
  INSERT ( [allColumns], 
           [id], 
           [lastmodified]) 
  VALUES (src. [allColumns], 
          src.[id], 
          src.[lastmodified]); 


-- now we update the master from the client
-- Note:
-- because the serverDB is a linked server 
-- we can't use another MERGE statement, otherwise
-- we get the error: "The target of a MERGE statement 
-- cannot be a remote table, a remote view, or a view over remote tables."

UPDATE
    serverDB

SET 
    [allColumns]        = [localDB].[allColumns],
    [id]                = [localDB].[id], 
    [lastmodified]      = [localDB].[lastmodified] 

FROM 
     [Server].[Clayton].[dbo].[tableName] serverDB

INNER JOIN
     [LocalClaytonDB].[dbo].[tableName] localDB

-- update where the id is the same but the client is newer than the master

ON serverDB.id = localDB.id 
       AND localDB.lastmodified >= serverDB.lastmodified

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多