我有两个表,Table1和Table2,它们有N个。列。我需要根据Table2更新Table1。我想更新Table1中列出Table2中单个列的所有列。
E.G
Table1 A B C D E . . .
1 2 3 4 5 . . .
7 6 5 4 3 . . .
Table2 X Y Col_Nam Col_Value
1 2 C 8
1 2 D 9
7 6 E 10
7 6 C 20
. . . .
. . . .
当匹配以下条件Table1.A = Table2.X时,更新表1中列出的表1中的所有列 和Table1.B = Table2.Y
平台是SQL Server。 我正在寻找的是一个动态的解决方案,因为我不知道我要更新的列名。表1可以有N号。需要更新的列。我使用Cursor尝试了以下内容。
DECLARE @s Varchar(MAX), @key1 VARCHAR(MAX), @key2 VARCHAR(MAX), @Cname VARCHAR(MAX), @CValue VARCHAR(MAX)
DECLARE crs CURSOR FOR SELECT * FROM Table2
OPEN crs;
FETCH NEXT FROM crs inTO @key1,@key2,@Cname,@Cvalue;
WHILE @@FETCH_STATUS = 0
BEGIN
set @s =
'Update T1 SET ' + @FieldName + ' = ''' + @FieldValue +
''' from Table1 T1' +
' where T1.A = ''' + @key1 +
''' and T1.B = ''' + @key2
exec(@s)
FETCH NEXT FROM crs inTO @key1,@key2,@Cname,@Cvalue;
END
CLOSE crs
DEALLOCATE crs
不知怎的,它不起作用,我想为那些与where条件不匹配的记录设置一个默认值。
任何其他解决方案或帮助将不胜感激。
答案 0 :(得分:1)
警告:在使用任何动态SQL之前,请阅读SQL Injection。在您的情况下,如果用户有权访问table2,则可以通过将sql代码写入col_name来进行攻击。
declare @X int, @Y int, @stmt nvarchar(max), @params nvarchar(max)
select @params = '@X int, @Y int'
declare table_cursor cursor local fast_forward for
select distinct X, Y from Table2
open table_cursor
while 1 = 1
begin
fetch table_cursor into @X, @Y
if @@fetch_status <> 0 break
select @stmt = null
select @stmt =
isnull(@stmt + ', ', '') +
Col_Name + ' = ' + cast(Col_Value as nvarchar(max))
from Table2
where X = @X and Y = @Y
select @stmt = 'update Table1 set ' + @stmt + ' where A = @X and B = @Y'
exec dbo.sp_executesql
@stmt = @stmt,
@params = @params,
@X = @X,
@Y = @Y
end
close table_cursor
deallocate table_cursor
答案 1 :(得分:0)
执行此操作的标准SQL方法需要相关的子查询:
update table1
set C = coalesce((select max(col_value)
from Table2 t2
where table1.A = t2.X and table1.B = t2.Y and
t2.Col_Name = 'A'
), C),
D = coalesce((select max(col_value)
from Table2 t2
where table1.A = t2.X and table1.B = t2.Y and
t2.Col_Name = 'D'
), D)
某些SQL引擎允许加入。以下是与MySQL一起使用的方法:
update table1 join
(select X, Y, max(case when col_name = 'C' then col_value end) as C,
max(case when col_name = 'D' then col_value end) as D
from table2
group by X, Y
) t2
on t2.X = table1.A and t2.Y = table2.Y
set C = coalesce(t2.C, C),
D = coalesce(t2.D, D)
在这两种情况下,coalesce()
用于在没有匹配时保持当前值。如果您希望NULL
不匹配,请删除coalesce()
。
修改
在SQL Server中,更新/加入的语法略有不同:
update table1 join
set C = coalesce(t2.C, C),
D = coalesce(t2.D, D)
from table1 join
(select X, Y, max(case when col_name = 'C' then col_value end) as C,
max(case when col_name = 'D' then col_value end) as D
from table2
group by X, Y
) t2
on t2.X = table1.A and t2.Y = table2.Y;