朋友们帮我看看这贴.

wag_enu 2009-11-06 03:57:29
http://topic.csdn.net/u/20091106/13/67796069-5bce-4d21-a671-e7928b9f11da.html

关于触发器的:

一个源库中的表更新后只同步一个目的库中的表倒还没什么问题。
但是现在要从一个源库中的表更新多个(不确定数量和名称)目的数据库中相同的表,
这样的触发器要怎么写?
...全文
140 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
wag_enu 2009-11-11
  • 打赏
  • 举报
回复
谢谢 #14楼 永生的帮助:
最后是结合了程序和你的方法解决了问题.
31737951 2009-11-10
  • 打赏
  • 举报
回复
如果数据库在一台机器上可以的,不在一台机器上就千万别搞了,除非你的机器很nb

关于触发器的写法,呵呵。我有一bt招数

就是动态生成触发器,增加或减少帐套后 库就固定了 再生成 触发器,毕竟帐套变动少

还有触发器 还是少用游标 和动态语法,除非你想执行完一个抽只烟再等下一个执行,触发器效率本来就低,语法效率再不高的话 只能等死锁了
wsz0812 2009-11-10
  • 打赏
  • 举报
回复
顶着
pacunove 2009-11-08
  • 打赏
  • 举报
回复
永生天地 2009-11-08
  • 打赏
  • 举报
回复
根据你的问题描述,我建了测试环境,只是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



sun1976 2009-11-08
  • 打赏
  • 举报
回复
这个不熟,个人感觉然后用触发器调用存储过程能比较容易些
建议sql版问问邹健去
wag_enu 2009-11-08
  • 打赏
  • 举报
回复
再 up 一下.
wag_enu 2009-11-07
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jlwei888 的回复:]
数据库的库能确定的用触发器,不能确定的用程序处理吧!
[/Quote]
[Quote=引用 10 楼 opet98765 的回复:]
通过游标从master表gaccount中逐个读出其中的dbname,然后将SQL通过拼成字符串的方式,先把SQL拼成字符串变量@sql,然后再exec(@sql)这个思路行不行?

[/Quote]

我也是这样想的:
用程序获取账套列表中的数据库名称列表,然后在程序中拼接用于创建触发器的SQL 字符串,再用dynamic SQL1 在源库中对应表上创建触发器,
有多少个需要更新的数据库就建多少个对应的触发器.

不知道还有没有更妙的方法.

期待中...
qq_1919561306 2009-11-07
  • 打赏
  • 举报
回复
通过游标从master表gaccount中逐个读出其中的dbname,然后将SQL通过拼成字符串的方式,先把SQL拼成字符串变量@sql,然后再exec(@sql)这个思路行不行?
wag_enu 2009-11-06
  • 打赏
  • 举报
回复
ls的朋友,我也搜到了本坛子中相关的贴子,也拜读过你以前的发言.
但是现在我的情况是:
同机不同库.每个库的结构一样,但是待同步的目的库的数量和名称都未知(得从一个指定的列表中获取,并且这个表随用户增加或删除账套而改变).
dawugui 2009-11-06
  • 打赏
  • 举报
回复
如果是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 本地表


hchjjun 2009-11-06
  • 打赏
  • 举报
回复
多个数据库如果是在一个服务器比较好办,如果没在一个数据库服务上还是比较危险的,极有可能出现数据不一致的情况。
蛇尾巴草 2009-11-06
  • 打赏
  • 举报
回复
用程序處理,觸發器更新多個數據庫沒做過
wag_enu 2009-11-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 jlwei888 的回复:]
数据库的库能确定的用触发器,不能确定的用程序处理吧!
[/Quote]

如果不行,只好这样了.
永生天地 2009-11-06
  • 打赏
  • 举报
回复
都来jf了
jlwei888 2009-11-06
  • 打赏
  • 举报
回复
数据库的库能确定的用触发器,不能确定的用程序处理吧!
jlwei888 2009-11-06
  • 打赏
  • 举报
回复
我也先顶再看
qq_1919561306 2009-11-06
  • 打赏
  • 举报
回复
这么多分先顶再看。

752

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧