更新表而不替换原始表中已存在的值,并使用临时表

时间:2015-09-09 08:18:05

标签: sql sql-server tsql sql-server-2008-r2

我有一个名为'student'的原始表格,如下所示:

idstudent    studentname    studentclass
101          adam           A
102          brian          NULL
103          charlie        C 
104          danny          D

然后,我有一个临时表名'student_temp',如下所示:

idstudent    studentname    studentclass
101          adam           A
102          brian          B
103          NULL           C
105          edward         E

如果我在SQL Server Management Studio 2008 R2上运行此查询:

USE [StudentDatabase]
GO

UPDATE stu
SET [studentname] = tmp.[studentname]
  , [studentclass] = tmp.[studentclass]

FROM [StudentDatabase].[dbo].[student] stu
INNER JOIN [StudentDatabase].[dbo].[student_temp] tmp  
    ON stu.[idstudent] = tmp.[idstudent]
GO

INSERT INTO student
SELECT 
    tmp.[idstudent]
  , tmp.[studentname]
  , tmp.[studentclass]

FROM [StudentDatabase].[dbo].[student] stu
RIGHT OUTER JOIN [StudentDatabase].[dbo].[student_temp] tmp 
    ON  stu.[idstudent] = tmp.[idstudent]
WHERE stu.[idstudent] IS NULL

'student'表的结果将是这样的:

idstudent    studentname    studentclass
101          adam           A
102          brian          B
103          NULL           C
104          danny          D
105          edward         E

但我想要的是,结果将是这样的:

idstudent    studentname    studentclass
101          adam           A
102          brian          B
103          charlie        C
104          danny          D
105          edward         E

请注意idstudent=103表中的student已经有studentname值“charlie”。但它被student_temp表中的记录替换为NULL

有什么方法可以解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

使用WHERE子句中的条件忽略NULL

UPDATE stu
SET [studentname] = tmp.[studentname]
  , [studentclass] = tmp.[studentclass]

FROM [StudentDatabase].[dbo].[student] stu
INNER JOIN [StudentDatabase].[dbo].[student_temp] tmp  
    ON stu.[idstudent] = tmp.[idstudent]
WHERE tmp.[studentname] IS NOT NULL

答案 1 :(得分:1)

通常应该使用MERGECOALESCE

完成整个过程
MERGE INTO student t
USING student_temp s
ON t.idstudent = s.idstudent
WHEN MATCHED THEN UPDATE SET
  studentname = COALESCE(t.studentname,s.studentname),
  studentclass = COALESCE(t.studentclass,s.studentclass)
WHEN NOT MATCHED THEN INSERT (idstudent,studentname,studentclass)
VALUES (s.idstudent,s.studentname,s.studentclass);

如果两个表都具有非空值,则此当前优先于现有数据。如果您希望使用student_temp中的新值覆盖,请反转COALESCE表达式中值的顺序。

所以,更喜欢student_temp的值:

MERGE INTO student t
USING student_temp s
ON t.idstudent = s.idstudent
WHEN MATCHED THEN UPDATE SET
  studentname = COALESCE(s.studentname,t.studentname),
  studentclass = COALESCE(s.studentclass,t.studentclass)
WHEN NOT MATCHED THEN INSERT (idstudent,studentname,studentclass)
VALUES (s.idstudent,s.studentname,s.studentclass);

答案 2 :(得分:0)

试试这个:

UPDATE stu
SET [studentname] = CASE WHEN tmp.[studentname] IS NOT NULL THEN tmp.[studentname] ELSE stu.studentname END
  , [studentclass] = CASE WHEN tmp.[studentclass] IS NOT NULL THEN tmp.[studentclass] ELSE stu.studentclass END

FROM [student] stu
INNER JOIN [student_temp] tmp  
    ON stu.[idstudent] = tmp.[idstudent]
GO

INSERT INTO student
SELECT 
    tmp.[idstudent]
  , tmp.[studentname]
  , tmp.[studentclass]

FROM [student] stu
RIGHT OUTER JOIN [student_temp] tmp 
    ON  stu.[idstudent] = tmp.[idstudent]
WHERE stu.[idstudent] IS NULL