朋友们帮我看看这贴.
http://topic.csdn.net/u/20091106/13/67796069-5bce-4d21-a671-e7928b9f11da.html
关于触发器的:
一个源库中的表更新后只同步一个目的库中的表倒还没什么问题。
但是现在要从一个源库中的表更新多个(不确定数量和名称)目的数据库中相同的表,
这样的触发器要怎么写?
[解决办法]
这么多分先顶再看。
[解决办法]
数据库的库能确定的用触发器,不能确定的用程序处理吧!
[解决办法]
用程序處理,觸發器更新多個數據庫沒做過
[解决办法]
多个数据库如果是在一个服务器比较好办,如果没在一个数据库服务上还是比较危险的,极有可能出现数据不一致的情况。
[解决办法]
如果是SQL SERVER,
1.同机不同库
insert into servername1.dbname1.dbo.tb select ... from tb
2.如果是异机,则参考如下:
不同服务器数据库之间的数据操作--创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' exec sp_addlinkedsrvlogin 'ITSV ', 'false ',null, '用户名 ', '密码 ' --查询示例 select * from ITSV.数据库名.dbo.表名 --导入示例 select * into 表 from ITSV.数据库名.dbo.表名 --以后不再使用时删除链接服务器 exec sp_dropserver 'ITSV ', 'droplogins ' --连接远程/局域网数据(openrowset/openquery/opendatasource) --1、openrowset --查询示例 select * from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) --生成本地表 select * into 表 from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) --把本地表导入远程表 insert openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名) select *from 本地表 --更新本地表 update b set b.列A=a.列A from openrowset( 'SQLOLEDB ', 'sql服务器名 '; '用户名 '; '密码 ',数据库名.dbo.表名)as a inner join 本地表 b on a.column1=b.column1 --openquery用法需要创建一个连接 --首先创建一个连接创建链接服务器 exec sp_addlinkedserver 'ITSV ', ' ', 'SQLOLEDB ', '远程服务器名或ip地址 ' --查询 select * FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') --把本地表导入远程表 insert openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') select * from 本地表 --更新本地表 update b set b.列B=a.列B FROM openquery(ITSV, 'SELECT * FROM 数据库.dbo.表名 ') as a inner join 本地表 b on a.列A=b.列A --3、opendatasource/openrowset SELECT * FROM opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ' ).test.dbo.roy_ta --把本地表导入远程表 insert opendatasource( 'SQLOLEDB ', 'Data Source=ip/ServerName;User ID=登陆名;Password=密码 ').数据库.dbo.表名 select * from 本地表
[解决办法]
通过游标从master表gaccount中逐个读出其中的dbname,然后将SQL通过拼成字符串的方式,先把SQL拼成字符串变量@sql,然后再exec(@sql)这个思路行不行?
[解决办法]
这个不熟,个人感觉然后用触发器调用存储过程能比较容易些
建议sql版问问邹健去
[解决办法]
根据你的问题描述,我建了测试环境,只是goods表里就建了3个字段
写了触发器,解决了你的那两个问题
1是不知道如何读取账套列表中的数据库列表和如何根据该数据库循环;
2是不知道如何处理标识列,当insert 时,做了SET IDENTITY_INSERT ab.dbo.goods ON 了还是提示:
具体做法见下面触发器,只写了insert的,update和delete的应该更容易
CREATE TRIGGER tri_goods ON [dbo].[goods]
for INSERT
as
declare @dbname varchar(20)
declare @sql varchar(4000)
declare @err int
declare @goodsid int
declare @rec int
declare @name varchar(50)
begin tran
select @goodsid=goodsid,@rec=rec,@name=name from inserted
--insert into #tmp select goodsid,rec,name from inserted
declare cur_db cursor for select dbname from master..gaccount
open cur_db
FETCH NEXT FROM cur_db INTO @dbname
WHILE @@FETCH_STATUS = 0
begin
if @dbname='Try2009a'
begin
FETCH NEXT FROM cur_db INTO @dbname
continue
end
set @sql = N'insert into '+ @dbname+'.dbo.goods(goodsid,rec,name) values( '+cast(@goodsid as varchar(20))+','+cast(@rec as varchar(20))+','''+@name+''')'
--set @sql = N'insert into '+ @dbname+'.dbo.goods(goodsid,rec,name) values(1,1,''111'' ) '
print @sql
--set IDENTITY_INSERT Try2009a..goods off
execute ('set IDENTITY_INSERT '+@dbname +'.dbo.goods on ' + @sql)
--execute (@sql)
print 'A check constraint violation occurred'
execute ('set IDENTITY_INSERT '+@dbname +'.dbo.goods off')
--exec sp_executesql @sql
if @@error<>0
begin
set @err = 1
print 'A check constraint violation occurred'
break
end
FETCH NEXT FROM cur_db INTO @dbname
end
close cur_db
DEALLOCATE cur_db
if @err=1
begin
delete from goods where goodsid=( select goodsid from goodsid)
rollback tran
end
else
--set IDENTITY_INSERT Try2009a..goods on
--insert into goods(goodsid,rec,name) select goodsid,rec,name from inserted
commit tran
CREATE TRIGGER tri_goods ON [dbo].[goods]
for INSERT, UPDATE, DELETE
as
declare @dbname varchar(20)
declare @sql varchar(4000)
declare @err int
declare @goodsid int
declare @rec int
declare @name varchar(50)
begin tran
select @goodsid=goodsid,@rec=rec,@name=name from inserted
--insert into #tmp select goodsid,rec,name from inserted
declare cur_db cursor for select dbname from master..gaccount
open cur_db
FETCH NEXT FROM cur_db INTO @dbname
WHILE @@FETCH_STATUS = 0
begin
if @dbname='Try2009a'
begin
FETCH NEXT FROM cur_db INTO @dbname
continue
end
set @sql = N'insert into '+ @dbname+'.dbo.goods(goodsid,rec,name) values( '+cast(@goodsid as varchar(20))+','+cast(@rec as varchar(20))+','''+@name+''')'
--set @sql = N'insert into '+ @dbname+'.dbo.goods(goodsid,rec,name) values(1,1,''111'' ) '
print @sql
--set IDENTITY_INSERT Try2009a..goods off
execute ('set IDENTITY_INSERT '+@dbname +'.dbo.goods on ' + @sql)
--execute (@sql)
print 'A check constraint violation occurred'
execute ('set IDENTITY_INSERT '+@dbname +'.dbo.goods off')
--exec sp_executesql @sql
if @@error<>0
begin
set @err = 1
print 'A check constraint violation occurred'
break
end
FETCH NEXT FROM cur_db INTO @dbname
end
close cur_db
DEALLOCATE cur_db
if @err=1
begin
delete from goods where goodsid=( select goodsid from goodsid)
rollback tran
end
else
--set IDENTITY_INSERT Try2009a..goods on
--insert into goods(goodsid,rec,name) select goodsid,rec,name from inserted
commit tran
--insert into goods(goodsid,name) values(3,'3')
--select * from goods
[解决办法]
顶
[解决办法]
顶着
[解决办法]
如果数据库在一台机器上可以的,不在一台机器上就千万别搞了,除非你的机器很nb
关于触发器的写法,呵呵。我有一bt招数
就是动态生成触发器,增加或减少帐套后 库就固定了 再生成 触发器,毕竟帐套变动少
还有触发器 还是少用游标 和动态语法,除非你想执行完一个抽只烟再等下一个执行,触发器效率本来就低,语法效率再不高的话 只能等死锁了