深度数据对接 链接服务器 数据传输
1.场景介绍
公司最近接了个客户,客户自有ERP技术C++ oracle,公司提供MES\APS等系统,因为客户很有钱,所以客户买了很好的服务器,因为有个很好的服务器,所以客户就只有一种类型的数据源就是oracle.
又因为数据源上有很重要的客户资料和营收信息,客户方经理以物理隔离为由让我们离他们的数据源远一点.只能通过接口访问,这个可以理解.然后我说是用webservice还是用webAPI,因为要深度对接
正考虑这么做要被搞死以后,客户技术经理说,这些太麻烦我们用链接服务器.我开放增删改查给你们. (゚Д゚#) (゚Д゚#) (゚Д゚#) (゚Д゚#) .嗯! 果然离的很远.
因为是ERP和MES对接,对于订单\BOM\人员\工艺\运行参数\叠构图\工序\排班\产能等模块都需要深度对接,要承接过来,并且客户做的修改必须及时反馈到各个系统上.关键是工艺和运行参数,如果这些在
ERP上修改了必须及时反馈到MES上,否则生产的产品有可能直接就报废了.本来纠结的事情随着使用链接服务器直接排除.
2.链接服务器搭建
--建立链接服务器 exec sp_addlinkedserver 'MY_LINK_SERVER','SQLSERVER','SQLOLEDB','192.168.1.1' exec sp_addlinkedsrvlogin 'MY_LINK_SERVER','false',null,'sa','123' EXEC sp_serveroption @server='MY_LINK_SERVER' , @optname= 'rpc', @optvalue ='TRUE' EXEC sp_serveroption @server='MY_LINK_SERVER' , @optname= 'rpc out', @optvalue='TRUE' --删除链接服务器 exec sp_dropserver 'MY_LINK_SERVER','droplogins' --查询所有可以使用的服务器 exec sp_helpserver
开启了rpc rpc out可以直接调用存储过程了,我觉得一些非涉及钱的业务,使用事务是给自己添堵,因为用事务占用表\占用锁比较多,如果是多人开发使用相同的模块,因为沟通和个人业务使用的不一致
死锁漫天飞,即造成了服务器资源的浪费又造成逻辑修改麻烦,我们项目组一般是使用业务数据验证来避免部分提交.就是提交完成后,检查下数据如果不符删了重来.所以我们在本地都很少用事务,更不要
说用远程分布式事务了.靠人不如靠自己.大家用业务检查的方式避免数据缺失.
3.使用远程数据
(1) 对于同是SQLserver 的数据库,可以直接使用
select * from MY_LINK_SERVER.TestDB.dbo.TestTable where file = 1
前面加个远程服务名,跟使用本地数据库一样,增删改查用的一样, rpc \ rpc out 两边配置相同,可以相互调用存储过程.这个使用起来没啥好讲的都一样.跟本地库操作差不多.
(2) 对于Oracle数据库使用起来没有那么方便,因为客户不给数据库名和各种信息,所以只能使用另外一种使用方式
select * from OPENQUERY(LINK_ERP,'SELECT * FROM TestTable')
or
select * from LINK_ERP.. S00.TESTTABLE
数据库内容访问对于 OPENQUERY(LINK_ERP,'SELECT * FROM TestDB') 是一个表集合 .类似一个临时的表集合.对于这个表过滤和使用跟其他内容一样,可使用查询排序功能类型这样
select * from OPENQUERY(LINK_ERP,'SELECT * FROM TestTable ') where file=1 order by file desc
(3) 对于这样使用方法,如果是表的体积比较小,或者数据比较少没有问题,如果表的数据比较多. 这种方式就有问题, 我们是testTable表中的所有数据从远程数据库中取完然后再本地建立的临时集合
然后过滤本地的临时数据然后输出结果.受远程表的影响\受网络传输的影响\受本地数据库性能影响,这样太不OK了.能不能跟使用本地表一样是用远程ORACLE数据库的表.对于这个问题,目前没有
良好的方法,我们试着把where 条件写到里面.
-- 所有条件入查询 select * from OPENQUERY(LINK_ERP,'SELECT * FROM TestTable where file = 1 order by file desc '); --所有条件入查询字符串 select * from OPENQUERY(LINK_ERP,'SELECT * FROM TestTable where fileName = ''test'' order by file desc ');
可以使用恒定值入表达式当成带条件的筛选了.字符串类型的需要添加转义符对传入的字符串进行转义,比如要表达出'test',在里面就得使用''test''这样的结构来表达出正确的.
这样减少返回的信息量,减少带宽的压力,减少本地缓存临时表的占用量.
(4) 很多同步数据和验证变量的时候往往并不使用常量来带入公式,需要使用变量来查询出来值.这时就需要根据对应的操作来实现这一操作.
declare @P_Control1 varchar(200) declare @P_Control2 int declare @execSQL varchar(2000) set @P_Control1 = 'justtest' set @P_Control2 = 2 -- 所有条件入查询 set @execSQL = 'select * from OPENQUERY(LINK_ERP,''SELECT * FROM TestTable where file = '+@P_Control2+' order by file desc '');' exec (@execSQL); ------------------------------------------------------------------------- --所有条件入查询字符串 set @execSQL = 'select * from OPENQUERY(LINK_ERP,''SELECT * FROM TestTable where fileName = '''''+@P_Control1 +''''' order by file desc '')'; exec(@execSQL); ------------------------------------------------------------------------- --中转临时表 set @execSQL = 'insert into localTestTable select * from OPENQUERY(LINK_ERP,''SELECT * FROM TestTable where fileName = '''''+@P_Control1 +''''' order by file desc '')'; exec(@execSQL); select * from localTestTable
分别是变量int\字符串\中转到本地临时表.都可以,这样使用变量特定的抓取.最后一个写字符串的反正就是加一层多家一个字符串.写到吐血.老实说目前只发现这种,如果谁有其他好的对接变量的可以分享一下.
这样写很考验耐心,而且容易出错.不过数据对接这样还是这样搞吧.