使用MERGE语句获取表(记录)以正确更新

时间:2012-05-12 06:35:05

标签: sql sql-server-2008 tsql

大家早上好!

下面是我拼凑的一段代码:我使用CTE从链接表中获取记录(数据),然后将字符串转换为日期,而不是使用merge语句将数据转换为本地表:

我遇到列(字段)问题LAST_RACE_DATE此字段设置为NULL并且不是必需的,但它不会使用我当前的设置进行更新。我想要完成的是这个字段在输入数据时填充但也更新,这意味着它也应该用NULL更新。

因此,如果该字段具有特定日期,并且在远程数据库中输入了新日期,则该字段也应该更新,即使在后端删除了数据,它也应该删除本地表数据这个领域。

WITH CTE AS(

SELECT MEMBER_ID
  ,[MEMBER_DATE] = MAX(CONVERT(DATE, MEMBER_DATE))
  ,RACE_DATE = MAX(CONVERT(DATE, RACE_DATE))
  ,LAST_RACE_DATE = MAX(CONVERT(DATE, LAST_RACE_DATE))

FROM [EXAMPLE].[dbo].[LINKED_MEMBER_DATA]
WHERE (MEMBER_DATE IS NOT NULL) AND (ISDATE(MEMBER_DATE)<> 0) AND (RACE_DATE IS NOT NULL) AND (ISDATE(RACE_DATE)<> 0) 
       AND (LAST_RACE_DATE IS NULL) OR (ISDATE(LAST_RACE_DATE)<> 0) 

GROUP BY MEMBER_ID)

MERGE dbo.LINKED_MEMBER_DATA AS Target
USING (SELECT 
  MEMBER_ID, MEMBER_DATE, RACE_DATE, LAST_RACE_DATE  

FROM CTE 

GROUP BY MEMBER_ID, RACE_DATE, LAST_RACE_DATE)AS SOURCE ON (Target.MEMBER_ID = SOURCE.MEMBER_ID) 

WHEN MATCHED AND 
   (Target.MEMBER_DATE)  <> (SOURCE.MEMBER_DATE)
OR (Target.RACE_DATE) <> (SOURCE.RACE_DATE)
OR ISNULL(TARGET.LAST_RACE_DATE , Target.LAST_RACE_DATE) <> ISNULL(SOURCE.LAST_RACE_DATE, SOURCE.LAST_RACE_DATE)

THEN UPDATE SET

 Target.MEMBER_DATE   =   SOURCE.MEMBER_DATE   
,Target.RACE_DATE  = SOURCE.RACE_DATE 
,Target.LAST_RACE_DATE = SOURCE.LAST_RACE_DATE

WHEN NOT MATCHED BY TARGET THEN
INSERT(
MEMBER_ID, MEMBER_DATE, RACE_DATE, LAST_RACE_DATE)

VALUES (Source.MEMBER_ID, Source.MEMBER_DATE, Source.RACE_DATE, Source.LAST_RACE_DATE);

我也试过这个:

ISNULL(Target.LAST_RACE_DATE,'N/A') <> ISNULL(SOURCE.LAST_RACE_DATE,'N/A')

但它会为日期转换生成以下错误:

从字符串转换日期和/或时间时转换失败。

感谢百万!!

1 个答案:

答案 0 :(得分:1)

您当前的语句失败,因为您没有做任何事情的ISNULL(如果其中一个值为NULL,表达式将计算为NULL),并且NULL值不进行比较。您的第二次尝试无效,因为ISNULL要求两个值的数据类型相同,因此您可以尝试ISNULL(Target.LAST_RACE_DATE, '1970-01-01') <> ISNULL(Source.LAST_RACE_DATE, '1970-01-01')

另一种选择是简单地枚举不同的情况(例如,(((Source.LAST_RACE_DATE IS NULL AND Target.LAST_RACE_DATE IS NOT NULL) OR (Source.LAST_RACE_DATE IS NOT NULL AND Target.LAST_RACE_DATE IS NULL) OR (Source.LAST_RACE_DATE <> Target.LAST_RACE_DATE)))。枚举不同的情况会使代码更加冗长,但它可以带来更好的性能(无论它是否真的更好)取决于您正在处理的数据量。)