通过使用Oracle作为中间容器编写存储过程,将Sql Server的数据实时同步到MySql,不直接在SqlServer中进行操作。
公司最近的项目要部署上线了,然后需要将甲方公司的ERP,OA,MES,PLM等系统的数据同步到我们的系统之中来,但是因为各个系统的厂家不一样有用友的ERP,致远的OA等等所以数据库有多种,Sql Server,Oracle,Mysql都有,而我们的系统使用的是Mysql,所以如何实现数据同步是个大问题。最初项目经理给出了几种方案,第一种是写定时任务定时的去取数据,第二种就是写存储过程去同步数据,无论哪种方式都需要有几个原则,首先是无论哪种方式都不可以直接在甲方公司的数据库上直接进行操作这是为了避免纠纷,第二个就是如果甲方的数据发生修改如何保证数据一致性。接下来我讲以从Sql Server同步到MySQL作为列子进行介绍。
1.找到需要同步的表
找到需要甲方的数据库你需要同步的表,然后确认好自己需要同步过去的数据有哪些,可以指定列可以不全部导入。
2.在自己的数据库中建立接收表
在自己的目标数据库中新建一张表接收数据,当然也可以不新建,如果有原始表可以将数据直接同步到原始表但是数据类型需要是一致的
3.编写存储过程
CREATE OR REPLACE PROCEDURE P_QUALICY_SPT IS
V_NUM1 number;
LI_RESULT_NO INTEGER;
LS_RESULT_TXT VARCHAR2(255);
BEGIN
FOR SE IN (SELECT ID,
CCHECKCODE,
CINSPECTCODE,
FQUANTITY,
FDTQUANTITY,
FDISBREAKQUANTITY,
FREGQUANTITY,
CSOURCE,
CINSPECTPERSON,
CDEFINE8,
DMAKETIME
FROM QMCHECKVOUCHER@Spt_Ufdata_Link) LOOP
SELECT count(1)
INTO V_NUM1
FROM "t_quality_spt"@spt_jzz_link
WHERE "ID" = SE.ID;
IF V_NUM1 < 1 THEN
-- insert
INSERT INTO "t_quality_spt"@spt_jzz_link
("ID",
"CCHECKCODE",
"CINSPECTCODE",
"FQUANTITY",
"FDTQUANTITY",
"FDISBREAKQUANTITY",
"FREGQUANTITY",
"CSOURCE",
"CINSPECTPERSON",
"CDEFINE8",
"DMAKETIME")
VALUES
(SE.ID,
SE.CCHECKCODE,
SE.CINSPECTCODE,
SE.FQUANTITY,
SE.FDTQUANTITY,
SE.FDISBREAKQUANTITY,
SE.FREGQUANTITY,
SE.CSOURCE,
SE.CINSPECTPERSON,
SE.CDEFINE8,
SE.DMAKETIME);
ELSE
-- update
UPDATE "t_quality_spt"@spt_jzz_link
SET "ID" = SE.ID,
"CCHECKCODE" = SE.CCHECKCODE,
"CINSPECTCODE" = SE.CINSPECTCODE,
"FQUANTITY" = SE.FQUANTITY,
"FDTQUANTITY" = SE.FDTQUANTITY,
"FDISBREAKQUANTITY" = SE.FDISBREAKQUANTITY,
"FREGQUANTITY" = SE.FREGQUANTITY,
"CSOURCE" = SE.CSOURCE,
"CINSPECTPERSON" = SE.CINSPECTPERSON,
"CDEFINE8" = SE.CDEFINE8,
"DMAKETIME" = SE.DMAKETIME
WHERE "ID" = SE.ID;
END IF;
END LOOP;
COMMIT;
----================================================== --
--================== --==================================================================== EXCEPTION
EXCEPTION
WHEN OTHERS THEN
LI_RESULT_NO := SQLCODE;
LS_RESULT_TXT := SQLERRM;
ROLLBACK;
RAISE_APPLICATION_ERROR(LI_RESULT_NO, LS_RESULT_TXT);
RETURN;
END P_QUALICY_SPT;
第一部分创建存储过程并定义变量
CREATE OR REPLACE PROCEDURE P_QUALICY_SPT IS
V_NUM1 number;
LI_RESULT_NO INTEGER;
LS_RESULT_TXT VARCHAR2(255);
第二部分查询出目标数据表的所有数据,并且跟自己的原始数据表进行判断,判断条件是是否存在这条数据(这里需要先新建好DB_Link来访问数据库)
BEGIN
FOR SE IN (SELECT ID,
CCHECKCODE,
CINSPECTCODE,
FQUANTITY,
FDTQUANTITY,
FDISBREAKQUANTITY,
FREGQUANTITY,
CSOURCE,
CINSPECTPERSON,
CDEFINE8,
DMAKETIME
FROM QMCHECKVOUCHER@Spt_Ufdata_Link) LOOP
SELECT count(1)
INTO V_NUM1
FROM "t_quality_spt"@spt_jzz_link
WHERE "ID" = SE.ID;
第三部分如果没有这条数据就插入
IF V_NUM1 < 1 THEN
-- insert
INSERT INTO "t_quality_spt"@spt_jzz_link
("ID",
"CCHECKCODE",
"CINSPECTCODE",
"FQUANTITY",
"FDTQUANTITY",
"FDISBREAKQUANTITY",
"FREGQUANTITY",
"CSOURCE",
"CINSPECTPERSON",
"CDEFINE8",
"DMAKETIME")
VALUES
(SE.ID,
SE.CCHECKCODE,
SE.CINSPECTCODE,
SE.FQUANTITY,
SE.FDTQUANTITY,
SE.FDISBREAKQUANTITY,
SE.FREGQUANTITY,
SE.CSOURCE,
SE.CINSPECTPERSON,
SE.CDEFINE8,
SE.DMAKETIME);
第四部分如果有则直接将目标数据修改到原始表保证数据一致
ELSE
-- update
UPDATE "t_quality_spt"@spt_jzz_link
SET "ID" = SE.ID,
"CCHECKCODE" = SE.CCHECKCODE,
"CINSPECTCODE" = SE.CINSPECTCODE,
"FQUANTITY" = SE.FQUANTITY,
"FDTQUANTITY" = SE.FDTQUANTITY,
"FDISBREAKQUANTITY" = SE.FDISBREAKQUANTITY,
"FREGQUANTITY" = SE.FREGQUANTITY,
"CSOURCE" = SE.CSOURCE,
"CINSPECTPERSON" = SE.CINSPECTPERSON,
"CDEFINE8" = SE.CDEFINE8,
"DMAKETIME" = SE.DMAKETIME
WHERE "ID" = SE.ID;
END IF;
END LOOP;
COMMIT;
第五部分结束过程
EXCEPTION
WHEN OTHERS THEN
LI_RESULT_NO := SQLCODE;
LS_RESULT_TXT := SQLERRM;
ROLLBACK;
RAISE_APPLICATION_ERROR(LI_RESULT_NO, LS_RESULT_TXT);
RETURN;
END P_QUALICY_SPT;
这时存储过程就编写完毕了
4.测试
在PL SQL中执行一下这段过程
已经新建好
5.执行
选中>右键Edit
选中存储过程的名称>右键Test
测试一下,这里跟DEBUG类似可以直接执行也可以步骤执行,如果没有报错证明存储过程写的没有问题
6.查看
刷新一下我们的表,可以发现数据已经同步过来了
到这里已经完成了数据同步,如果需要实时的同步的话则需要写个定时任务按照自己的需求去执行这个存储过程,如有遗漏欢迎指正。