--用触发器即时同步两个表的实例:--测试环境:SQL2000,远程主机名:xz,用户名:sa,密码:无,数据库名:test--创建测试表,不能用标识列做主键,因为不能进行正常更新
--在远程主机上建表
if exists (select * from dbo.sysobjects where id = object_id(N'[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [test]create table test(id int not null constraint PK_test primary key
,name varchar(10))
go--以下操作在本机进行
--在本机上建表及做同步处理的工作
if exists (select * from dbo.sysobjects where id = object_id(N'[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [test]create table test(id int identity(1,1) primary key
,name varchar(10))
go--创建同步的触发器
create trigger t_test on test
for insert,update,delete
as
set  XACT_ABORT on
--启动远程服务器的MSDTC服务
exec master..xp_cmdshell 'isql /S"xz" /U"sa" /P"" /q"exec master..xp_cmdshell ''net start msdtc'',no_output"',no_output--启动本机的MSDTC服务
exec master..xp_cmdshell 'net start msdtc',no_output--进行分布事务处理,如果表用标识列做主键,用下面的方法
BEGIN DISTRIBUTED TRANSACTION
delete from openrowset('sqloledb','xz';'sa';'',test.dbo.test)
where id in(select id from deleted)
insert into openrowset('sqloledb','xz';'sa';'',test.dbo.test)
select * from inserted
commit tran
go--插入数据测试
insert into test
select 1,'aa'
union all select 2,'bb'
union all select 3,'c'
union all select 4,'dd'
union all select 5,'ab'
union all select 6,'bc'
union all select 7,'ddd'--删除数据测试
delete from test where id in(1,4,6)--更新数据测试
update test set name=name+'_123' where id in(3,5)--显示测试的结果
select * from test a full join
openrowset('sqloledb','xz';'sa';'',test.dbo.test) b on a.id=b.id

解决方案 »

  1.   

    --定时同步服务器上的数据(本地的数据修改同步到服务器)--例子:
    --测试环境,SQL Server2000,远程服务器名:xz,用户名为:sa,无密码,测试数据库:test
    --服务器上的表(查询分析器连接到服务器上创建)
    if exists (select * from dbo.sysobjects where id = object_id(N'[user]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [user]create table [user](id int primary key,number varchar(4),name varchar(10))
    go--以下在局域网(本机操作)
    --state字段为辅助更新而设置的附加字段,字段值说明:null 表示新增记录,1 表示修改过的记录,0 表示无变化的记录
    if exists (select * from dbo.sysobjects where id = object_id(N'[user]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
    drop table [user]
    GO
    create table [user](id int identity(1,1) primary key,number varchar(4),name varchar(10),state bit)
    go
    --创建触发器,维护state字段的值
    create trigger t_state on [user]
    after update
    as
    update [user] set state=1
    from [user] a join inserted b on a.id=b.id
    where a.state is not null
    go--为了方便同步处理,创建链接服务器到要同步的服务器
    --这里的远程服务器名为:xz,用户名为:sa,无密码
    if exists(select 1 from master..sysservers where srvname='srv_lnk')
    exec sp_dropserver 'srv_lnk','droplogins'
    go
    exec sp_addlinkedserver  'srv_lnk','','SQLOLEDB','xz'
    exec sp_addlinkedsrvlogin 'srv_lnk','false',null,'sa'
    go--创建同步处理的存储过程
    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_synchro]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[p_synchro]
    GO
    create proc p_synchro
    as
    /*--因为MSDTC服务(分布式事务处理需要)工作不稳定,所以下面部分为选用内容
    --set  xact_abort on
    --启动远程服务器的MSDTC服务
    --exec master..xp_cmdshell 'isql /S"xz" /U"sa" /P"" /q"exec master..xp_cmdshell ''net start msdtc'',no_output"',no_output--启动本机的MSDTC服务
    --exec master..xp_cmdshell 'net start msdtc',no_output--进行分布事务处理,如果表用标识列做主键,用下面的方法
    --BEGIN DISTRIBUTED TRANSACTION
    --*/
    --同步删除的数据
    delete from srv_lnk.test.dbo.[user]
    where id not in(select id from [user]) --同步新增的数据
    insert into srv_lnk.test.dbo.[user]
    select id,number,name from [user] where state is null

    --同步修改的数据
    update srv_lnk.test.dbo.[user] set
    number=b.number,name=b.name
    from srv_lnk.test.dbo.[user] a
    join [user] b on a.id=b.id
    where b.state=1

    --同步后更新本机的标志
    update [user] set state=0 where isnull(state,1)=1
    --COMMIT TRAN --如果启用分布式事务处理,加上此句
    go--创建作业,定时执行数据同步的存储过程
    if exists(SELECT 1 from msdb..sysjobs where name='数据处理')
    EXECUTE msdb.dbo.sp_delete_job @job_name='数据处理'
    exec msdb..sp_add_job @job_name='数据处理'--创建作业步骤
    declare @sql varchar(800),@dbname varchar(250)
    select @sql='exec p_synchro'   --数据处理的命令
    ,@dbname=db_name() --执行数据处理的数据库名exec msdb..sp_add_jobstep @job_name='数据处理',
    @step_name = '数据同步',
    @subsystem = 'TSQL',
    @database_name=@dbname,
        @command = @sql,
    @retry_attempts = 5,  --重试次数
    @retry_interval = 5   --重试间隔--创建调度
    EXEC msdb..sp_add_jobschedule @job_name = '数据处理', 
    @name = '时间安排',
    @freq_type=4,   --4 每天,8 每周,16 每月
    @freq_interval=1, --作业执行的天数
    @freq_subday_type=0, --是否重复执行,0x1 在指定的时间, 0x4 分钟, 0x8 小时 
    @freq_subday_interval=1,  --重复周期
    @freq_recurrence_factor=0, --重复执行,则设置为1,否则设置为0
    @active_start_time = 00000 --0点开始执行--添加目标服务器
    EXEC msdb.dbo.sp_add_jobserver 
    @job_name = @jobname ,
    @server_name = N'(local)' 
    go
      

  2.   

    --配置分发服务器和发布服务器
    CREATE        PROCEDURE UP_ConfigDistributor
    (@publishServer varchar(50),
     @distributeServer varchar(50),
     @replicationDb varchar(50),
     @distributeDb varchar(50),
     @data_folder_path varchar(100),
    -- @working_directory_path nvarchar(255),
     @sUnitCode varchar(9)
    )

    AS
      --定义分发数据库数据文件
      declare @distributeDbDataFile varchar(100)
      select  @distributeDbDataFile = @distributeDb + '.MDF'
      --定义分发数据库日志文件
      declare @distributeDbLogFile varchar(100)
      select  @distributeDbLogFile = @distributeDb + '.LDF'
     declare @log_folder_path varchar(100)
     select @log_folder_path = @data_folder_path
     declare @temp1 varchar(100)
      select @temp1 = replace(@data_folder_path,':','$')
      select @temp1 = replace(@temp1,'Data','ReplData')
      declare @working_directory_path nvarchar(255)
      select @working_directory_path = '\\' + host_name() + '\' + @temp1
      --第一步:
    --定义分发服务器(执行一次)
    if not exists (select * from master..sysservers where lower(srvname) = 
                   'repl_distributor' collate database_default)
    begin
    exec master..sp_adddistributor  @distributor = @distributeServer , @password = N''
    end
    -- 添加分发数据库
    IF NOT EXISTS (SELECT * from master..sysdatabases WHERE name = @distributeDb collate database_default)
    begin
    exec master..sp_adddistributiondb  @database = @distributeDb, @data_folder = @data_folder_path, @data_file = @distributeDbDataFile, @data_file_size = 2, @log_folder = @log_folder_path, @log_file = @distributeDbLogFile, @log_file_size = 0, @min_distretention = 0, @max_distretention = 72, @history_retention = 48, @security_mode = 0, @login = N'sa', @password = null
    end
    --定义分发发布者(执行一次)
    IF NOT EXISTS (SELECT *
             FROM msdb..MSdistpublishers
            WHERE name = @publishServer collate database_default)
    begin
    -- 添加分发发布者
    exec master..sp_adddistpublisher  @publisher = @publishServer, @distribution_db = @distributeDb, @security_mode = 1, @working_directory = @working_directory_path, @trusted = N'false', @thirdparty_flag = 0
    end
    --启用复制数据库
    exec master..sp_replicationdboption @dbname = @replicationDb, @optname = N'merge publish', @value = N'true'GO
    SET QUOTED_IDENTIFIER OFF 
    GO
    SET ANSI_NULLS ON 
    GO
      

  3.   

    --配置订阅服务器
    CREATE     PROCEDURE UP_ConfigSubscriber
    (
    @publicationName varchar(50),
       @distributeDb varchar(50),
       @subscribeServer varchar(50),  
       @subscribeDb varchar(50),
       @subscribeLogin varchar(30),
       @subscribePassword varchar(30)     
    )
    AS
    -- 添加注册的订阅服务器
    exec ('select * from  ' + @distributeDb + '.dbo.MSsubscriber_info')
    if @@rowcount = 0
    begin
    exec master..sp_addsubscriber @subscriber = @subscribeServer, @type = 0, @login = @subscribeLogin, @password = @subscribePassword, @security_mode = 0, @frequency_type = 64, @frequency_interval = 1, @frequency_relative_interval = 2, @frequency_recurrence_factor = 0, @frequency_subday = 8, @frequency_subday_interval = 1, @active_start_date = 0, @active_end_date = 0, @active_start_time_of_day = 0, @active_end_time_of_day = 235900, @description = N''
    exec master..sp_changesubscriber_schedule @subscriber = @subscribeServer, @agent_type = 1, @active_end_date = 0
    end-- 添加合并订阅
     if NOT EXISTS (select db_name, srvid
    FROM sysmergesubscriptions
      WHERE db_name = @subscribeDb
                AND srvid = (select srvid from master..sysservers where srvname = @subscribeServer collate database_default)                          
                AND pubid = (select pubid FROM sysmergepublications 
                WHERE name = @publicationName) AND status <>2)
    begin
    exec sp_addmergesubscription @publication = @publicationName, @subscriber = @subscribeServer, @subscriber_db = @subscribeDb, @subscription_type = N'push', @subscriber_type = N'local', @subscription_priority = 0.000000, @sync_type = N'automatic', @frequency_type = 0x40, @frequency_interval = null, @frequency_relative_interval = 1, @frequency_recurrence_factor = 0, @frequency_subday = 8, @frequency_subday_interval = 1, @active_start_date = 0, @active_end_date = 0, @active_start_time_of_day = 0, @active_end_time_of_day = 235959, @enabled_for_syncmgr = N'false', @offloadagent = 0, @use_interactive_resolver = N'false'
    end
      

  4.   

    --创建发布
    use test   --test为发布数据库
    -- 添加合并发布
    exec sp_addmergepublication @publication = @publicationName, @description = N'', @retention = 14, @sync_mode = N'native', @allow_push = N'true', @allow_pull = N'true', @allow_anonymous = N'false', @enabled_for_internet = N'false', @centralized_conflicts = N'true', @dynamic_filters = N'false', @snapshot_in_defaultfolder = N'true', @compress_snapshot = N'false', @ftp_port = 21, @ftp_login = N'anonymous', @conflict_retention = 14, @keep_partition_changes = N'false', @allow_subscription_copy = N'false', @allow_synctoalternate = N'false', @add_to_active_directory = N'false', @max_concurrent_merge = 0, @max_concurrent_dynamic_snapshots = 0
    exec sp_addpublication_snapshot @publication = @publicationName,@frequency_type = 8, @frequency_interval = 64, @frequency_relative_interval = 0, @frequency_recurrence_factor = 1, @frequency_subday = 1, @frequency_subday_interval = 0, @active_start_date = 0, @active_end_date = 0, @active_start_time_of_day = 12300, @active_end_time_of_day = 0, @snapshot_job_name = @snapshotJobName-- 添加合并项目
    exec sp_addmergearticle @publication = @publicationName, @article = N'bFZRLS', @source_owner = N'dbo', @source_object = N'bFZRLS', @type = N'table', @description = null, @column_tracking = N'true', @pre_creation_cmd = N'drop', @creation_script = null, @schema_option = 0x000000000000CFF1, @article_resolver = null, @subset_filterclause = @publicationFilterCondition, @vertical_partition = N'false', @destination_owner = N'dbo', @auto_identity_range = N'false', @verify_resolver_signature = 0, @allow_interactive_resolver = N'false', @fast_multicol_updateproc = N'true', @check_permissions = 0
      

  5.   

    可以把上面的创建发布写成存储过程UP_CreatePublication,我自己刚刚做过此工作。
    在C#里用代码依次调用以上3个存储过程即可(UP_ConfigDistributor,UP_CreatePublication,UP_ConfigSubscriber).
    UP_CreatePublication可以先用可视化创建发布,然后查看sql教本获取