SQL Server 中如何根据一张表的数据自动更新另一张表的数据

时间:2022-12-04 00:52:40
需求:有两个表 A ,B 
SQL Server 中如何根据一张表的数据自动更新另一张表的数据
其中A表是动态变化的, 如何才能做到将A表的值插入到B表中,如果A.col1=B.col2 时 直接更新整列的数据,如果不等时,就直接插入数据。
用update 只能实现更新,不能实现把新的值插入。
麻烦大神帮帮忙,谢谢

23 个解决方案

#1


实时可以尝试触发器

#2


用【Merge into 】语法,不过您的数据库版本要在sql2008以上。
以下是Merge into的用法:
主键判断,如果有就update,没有就insert
http://blog.csdn.net/yole_grise/article/details/15337973

#3


引用 1 楼 xdashewan 的回复:
实时可以尝试触发器

触发器不太实用,因为这段sql 要每10分钟执行一次

#4


引用 3 楼 S_SUNY_1234 的回复:
触发器不太实用,因为这段sql 要每10分钟执行一次

那就搞个sql作业http://blog.csdn.net/szstephenzhou/article/details/7802308

#5


引用 3 楼 S_SUNY_1234 的回复:
Quote: 引用 1 楼 xdashewan 的回复:

实时可以尝试触发器

触发器不太实用,因为这段sql 要每10分钟执行一次



触发器可以满足,只要A表用动作就更新或是插入B表。
A表的动作无非就是 update 和 insert

#6


引用 2 楼 u010192842 的回复:
用【Merge into 】语法,不过您的数据库版本要在sql2008以上。
以下是Merge into的用法:
主键判断,如果有就update,没有就insert
http://blog.csdn.net/yole_grise/article/details/15337973


如果从A表中select时要加where 条件时 应该加在哪里?
例如: 只是把 col3>90 的数据更新到B 表中,而不是把所有值都更新。 

另外,A表是动态变化的,这个更新语句要每隔10分钟执行一次

#7


语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。

#8


数据量大的话最好是加上一列时间戳,通过时间戳去判断取数。不然当您的表数据超过百万甚至千万数据的时候,同步更新数据就会奇慢无比...

#9


引用 7 楼 u010192842 的回复:
语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。


就拿我这个例子来说,
1. 先在A表中进行查询: 
    
select col1, col2, col3 from A

2. 将A表查出来的数据插入到B表中:
    
merge into A 
    using B on B.col1 = A.col1
     when Matched  then update set B.col1 = A.col1
     when not Matched then insert (col1,col2,col3) values (select col1, col2, col3 from A) 

麻烦你花几分钟时间看看,我实在不知道这个where条件应该怎么写。

另外 您说的; 语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。能不能麻烦您大概写下代码。谢谢您哦

#10



引用 7 楼 u010192842 的回复:
语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。


上面那个有点错误,请忽略,以这个为准。
就拿我这个例子来说,
1. 先在A表中进行查询: 
    
select col1, col2, col3 from A where col3 >80

2. 将A表查出来的数据插入到B表中:
    
merge into A 
    using B on B.col1 = A.col1
     when Matched  then update set B.col1 = A.col1
     when not Matched then insert (col1,col2,col3) values (select col1, col2, col3 from A  where col3 >80) 

麻烦你花几分钟时间看看,我实在不知道这个where条件应该怎么写。

另外 您说的; 语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。能不能麻烦您大概写下代码。谢谢您哦

#11



--创建测试表    
CREATE TABLE t_A   
(MCLASS VARCHAR(20),SNO VARCHAR(20))    
INSERT INTO t_A    
SELECT 'L-1','123'    
UNION ALL    
SELECT  'L-2','234'    
UNION ALL    
SELECT 'L-3','345'  
  
CREATE TABLE t_B   
(MCLASS VARCHAR(20),SNO VARCHAR(20))    
INSERT INTO t_B    
SELECT 'L-1','999'    
UNION ALL    
SELECT  'L-2','999'    
UNION ALL    
SELECT 'L-4','888'  
  
--确定目标表  
merge into t_A as a    
--从t_B表中查找MCLASS相同的数据  
using t_B as b on a.MCLASS=b.MCLASS and a.mclass= 'L-1'--这里写条件
--当MCLASS相同时,则更新t_A中SNO字段  
when Matched then update set a.SNO=b.SNO   
--当t_A表中不存在MCLASS相同的数据时,则从t_B表插入目标表t_A  
when Not Matched then Insert(MCLASS,SNO) values(b.MCLASS,b.SNO);

select * from t_A
select * from t_B
drop table t_A
drop table t_B

#12



merge into A 
    using B on B.col1 = A.col1 --这里写条件 and a.col3 >80

#13


插b表的话,应该
merge into  B  --这里是B

#14


触发器为什么不行

#15


引用 14 楼 chenzhen260 的回复:
触发器为什么不行

因为后面还有个触发器依赖于这个结果

#16


引用 13 楼 u010192842 的回复:
插b表的话,应该
merge into  B  --这里是B

大神 谢谢您,现在可以执行了,5 s 就跑完了,很高效。

另外 你能告诉我怎么才能让这段sql 每十分钟执行一次吗?
谢谢您。

#17


新建一个作业(job),里面可以写代码,然后可以定时执行。
关于作业的写法,可以百度一下:
http://jingyan.baidu.com/article/49ad8bce7287315834d8fab4.html

#18


引用 17 楼 u010192842 的回复:
新建一个作业(job),里面可以写代码,然后可以定时执行。
关于作业的写法,可以百度一下:
http://jingyan.baidu.com/article/49ad8bce7287315834d8fab4.html

谢谢您,根据您的提示,我基本配好了,每10分钟跟新一次。
现在还有个疑问, 怎样才能通过触发器检测到更新后某列的值发生变化,就发邮件给用户,我把邮箱服务起配好了,不知道怎么用,能不能再看下,谢谢您

#20


引用 19 楼 u010192842 的回复:
http://blog.csdn.net/yole_grise/article/details/49637747
sql发邮件。

谢谢您快速恢复,您博客里写的我也配好了,不知道怎么用触发器来检测,当某列发生变化时才发邮件,能不能抽时间简单写下。谢谢

#21


触发器可不行吧,改变的数据您可以记到一个表中,然后定时去查那个表,然后有您做了改变的数据插入该表,就发送邮件。

#22


这样比 update 快


delete b where id in (select id from a)
insert b select * from a

#23


引用 20 楼 S_SUNY_1234 的回复:
Quote: 引用 19 楼 u010192842 的回复:

http://blog.csdn.net/yole_grise/article/details/49637747
sql发邮件。

谢谢您快速恢复,您博客里写的我也配好了,不知道怎么用触发器来检测,当某列发生变化时才发邮件,能不能抽时间简单写下。谢谢

您好, 我写了一个触发器,但是好像没有成功,就是在Priority 那一列由1变为0的时候,没有出发邮件,麻烦您再给看看

CREATE TRIGGER Reminder_Helpdesk
on dbo.helpdesk
after update 
as 
begin
declare @INCIDENT_ID nvarchar(15) 
declare @PRIORITY nvarchar(20) 
declare @PRIORITY_NEW nvarchar(20)

IF UPDATE (PRIORITY)
BEGIN
   
declare cur_helpdesk cursor for select INCIDENT_ID, PRIORITY from DELETED
        open cur_helpdesk
        fetch next from cur_helpdesk into @INCIDENT_ID, @PRIORITY
        while @@FETCH_STATUS =0
        begin
            select @PRIORITY_new=[PRIORITY] from INSERTED where INCIDENT_ID=INCIDENT_ID
            if (@PRIORITY_new<@PRIORITY)
            begin
                insert into UpdateLog(priority) values(@PRIORITY+'    '+@PRIORITY_new)
            end
            fetch next from cur_helpdesk into @INCIDENT_ID, @PRIORITY
        end
    begin 
 EXEC msdb.dbo.sp_send_dbmail

            @recipients = 'test@163.com', 
            @message    = 'There is message', 
            @subject    = 'There is a message';

end 
        close cur_helpdesk
      deallocate cur_helpdesk
    end
END

#1


实时可以尝试触发器

#2


用【Merge into 】语法,不过您的数据库版本要在sql2008以上。
以下是Merge into的用法:
主键判断,如果有就update,没有就insert
http://blog.csdn.net/yole_grise/article/details/15337973

#3


引用 1 楼 xdashewan 的回复:
实时可以尝试触发器

触发器不太实用,因为这段sql 要每10分钟执行一次

#4


引用 3 楼 S_SUNY_1234 的回复:
触发器不太实用,因为这段sql 要每10分钟执行一次

那就搞个sql作业http://blog.csdn.net/szstephenzhou/article/details/7802308

#5


引用 3 楼 S_SUNY_1234 的回复:
Quote: 引用 1 楼 xdashewan 的回复:

实时可以尝试触发器

触发器不太实用,因为这段sql 要每10分钟执行一次



触发器可以满足,只要A表用动作就更新或是插入B表。
A表的动作无非就是 update 和 insert

#6


引用 2 楼 u010192842 的回复:
用【Merge into 】语法,不过您的数据库版本要在sql2008以上。
以下是Merge into的用法:
主键判断,如果有就update,没有就insert
http://blog.csdn.net/yole_grise/article/details/15337973


如果从A表中select时要加where 条件时 应该加在哪里?
例如: 只是把 col3>90 的数据更新到B 表中,而不是把所有值都更新。 

另外,A表是动态变化的,这个更新语句要每隔10分钟执行一次

#7


语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。

#8


数据量大的话最好是加上一列时间戳,通过时间戳去判断取数。不然当您的表数据超过百万甚至千万数据的时候,同步更新数据就会奇慢无比...

#9


引用 7 楼 u010192842 的回复:
语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。


就拿我这个例子来说,
1. 先在A表中进行查询: 
    
select col1, col2, col3 from A

2. 将A表查出来的数据插入到B表中:
    
merge into A 
    using B on B.col1 = A.col1
     when Matched  then update set B.col1 = A.col1
     when not Matched then insert (col1,col2,col3) values (select col1, col2, col3 from A) 

麻烦你花几分钟时间看看,我实在不知道这个where条件应该怎么写。

另外 您说的; 语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。能不能麻烦您大概写下代码。谢谢您哦

#10



引用 7 楼 u010192842 的回复:
语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。


上面那个有点错误,请忽略,以这个为准。
就拿我这个例子来说,
1. 先在A表中进行查询: 
    
select col1, col2, col3 from A where col3 >80

2. 将A表查出来的数据插入到B表中:
    
merge into A 
    using B on B.col1 = A.col1
     when Matched  then update set B.col1 = A.col1
     when not Matched then insert (col1,col2,col3) values (select col1, col2, col3 from A  where col3 >80) 

麻烦你花几分钟时间看看,我实在不知道这个where条件应该怎么写。

另外 您说的; 语句写到作业里面,作业可以执行存储过程,判断语句写到过程里。能不能麻烦您大概写下代码。谢谢您哦

#11



--创建测试表    
CREATE TABLE t_A   
(MCLASS VARCHAR(20),SNO VARCHAR(20))    
INSERT INTO t_A    
SELECT 'L-1','123'    
UNION ALL    
SELECT  'L-2','234'    
UNION ALL    
SELECT 'L-3','345'  
  
CREATE TABLE t_B   
(MCLASS VARCHAR(20),SNO VARCHAR(20))    
INSERT INTO t_B    
SELECT 'L-1','999'    
UNION ALL    
SELECT  'L-2','999'    
UNION ALL    
SELECT 'L-4','888'  
  
--确定目标表  
merge into t_A as a    
--从t_B表中查找MCLASS相同的数据  
using t_B as b on a.MCLASS=b.MCLASS and a.mclass= 'L-1'--这里写条件
--当MCLASS相同时,则更新t_A中SNO字段  
when Matched then update set a.SNO=b.SNO   
--当t_A表中不存在MCLASS相同的数据时,则从t_B表插入目标表t_A  
when Not Matched then Insert(MCLASS,SNO) values(b.MCLASS,b.SNO);

select * from t_A
select * from t_B
drop table t_A
drop table t_B

#12



merge into A 
    using B on B.col1 = A.col1 --这里写条件 and a.col3 >80

#13


插b表的话,应该
merge into  B  --这里是B

#14


触发器为什么不行

#15


引用 14 楼 chenzhen260 的回复:
触发器为什么不行

因为后面还有个触发器依赖于这个结果

#16


引用 13 楼 u010192842 的回复:
插b表的话,应该
merge into  B  --这里是B

大神 谢谢您,现在可以执行了,5 s 就跑完了,很高效。

另外 你能告诉我怎么才能让这段sql 每十分钟执行一次吗?
谢谢您。

#17


新建一个作业(job),里面可以写代码,然后可以定时执行。
关于作业的写法,可以百度一下:
http://jingyan.baidu.com/article/49ad8bce7287315834d8fab4.html

#18


引用 17 楼 u010192842 的回复:
新建一个作业(job),里面可以写代码,然后可以定时执行。
关于作业的写法,可以百度一下:
http://jingyan.baidu.com/article/49ad8bce7287315834d8fab4.html

谢谢您,根据您的提示,我基本配好了,每10分钟跟新一次。
现在还有个疑问, 怎样才能通过触发器检测到更新后某列的值发生变化,就发邮件给用户,我把邮箱服务起配好了,不知道怎么用,能不能再看下,谢谢您

#19


#20


引用 19 楼 u010192842 的回复:
http://blog.csdn.net/yole_grise/article/details/49637747
sql发邮件。

谢谢您快速恢复,您博客里写的我也配好了,不知道怎么用触发器来检测,当某列发生变化时才发邮件,能不能抽时间简单写下。谢谢

#21


触发器可不行吧,改变的数据您可以记到一个表中,然后定时去查那个表,然后有您做了改变的数据插入该表,就发送邮件。

#22


这样比 update 快


delete b where id in (select id from a)
insert b select * from a

#23


引用 20 楼 S_SUNY_1234 的回复:
Quote: 引用 19 楼 u010192842 的回复:

http://blog.csdn.net/yole_grise/article/details/49637747
sql发邮件。

谢谢您快速恢复,您博客里写的我也配好了,不知道怎么用触发器来检测,当某列发生变化时才发邮件,能不能抽时间简单写下。谢谢

您好, 我写了一个触发器,但是好像没有成功,就是在Priority 那一列由1变为0的时候,没有出发邮件,麻烦您再给看看

CREATE TRIGGER Reminder_Helpdesk
on dbo.helpdesk
after update 
as 
begin
declare @INCIDENT_ID nvarchar(15) 
declare @PRIORITY nvarchar(20) 
declare @PRIORITY_NEW nvarchar(20)

IF UPDATE (PRIORITY)
BEGIN
   
declare cur_helpdesk cursor for select INCIDENT_ID, PRIORITY from DELETED
        open cur_helpdesk
        fetch next from cur_helpdesk into @INCIDENT_ID, @PRIORITY
        while @@FETCH_STATUS =0
        begin
            select @PRIORITY_new=[PRIORITY] from INSERTED where INCIDENT_ID=INCIDENT_ID
            if (@PRIORITY_new<@PRIORITY)
            begin
                insert into UpdateLog(priority) values(@PRIORITY+'    '+@PRIORITY_new)
            end
            fetch next from cur_helpdesk into @INCIDENT_ID, @PRIORITY
        end
    begin 
 EXEC msdb.dbo.sp_send_dbmail

            @recipients = 'test@163.com', 
            @message    = 'There is message', 
            @subject    = 'There is a message';

end 
        close cur_helpdesk
      deallocate cur_helpdesk
    end
END