Merge语句每次运行时为什么会将所有数据插入目标表中?

huangapple go评论73阅读模式
英文:

Why merge statement inserts all the data into the target table each time it runs?

问题

I have these two table with same schema and records on different server and databases.

If the record in source table gets added or modified then it should be reflected in the target table as well but for some weird reasons it inserts all the rows in the target table each time.

I just want it to insert if a new row gets added in the source or modified in the source.

Code:

MERGE INTO dbo.CountrySourceType AS target
USING (
    SELECT Id = Id * (- 1)
        , Name
        , (
            SELECT Id
            FROM country c
            WHERE ISNULL(c.Name, '') = (
                    SELECT ISNULL(cs.Name, '') Name
                    FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                    WHERE cs.Id = cst.CountryId
                    )
                AND ISNULL(c.ContinentName, '') = (
                    SELECT ISNULL(cs.ContinentName, '') ContinentName
                    FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                    WHERE cs.Id = cst.CountryId
            )
    ) CountryId
    FROM [192.xxx.x.xxx].WebPortal.dbo.CountrySourceType cst
    WHERE CountryId = cst.CountryId
    ) AS source
    ON source.Id = target.Id
WHEN NOT MATCHED BY target
    THEN
        INSERT (
            [Name],
            [CountryId]
            )
        VALUES (
             source.Name
            ,source.CountryId

            );

I tried it using the merge and narrowed down using the where clause but still it doesn't.

英文:

I have these two table with same schema and records on different server and databases.

If the record in source table gets added or modified then it should be reflected in the target table as well but for some weird reasons it inserts all the rows in the target table each time.

I just want it to insert if new row gets added in the source or modified in the source.

Code:

MERGE INTO dbo.CountrySourceType AS target
USING (
				SELECT Id = Id * (- 1)
					, Name
					, (
						SELECT Id
						FROM country c
						WHERE ISNULL(c.Name, '') = (
								SELECT ISNULL(cs.Name, '') Name
								FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
								WHERE cs.Id = cst.CountryId
								)
							AND ISNULL(c.ContinentName, '') = (
								SELECT ISNULL(cs.ContinentName, '') ContinentName
								FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
								WHERE cs.Id = cst.CountryId
						)
				) CountryId
				FROM [192.xxx.x.xxx].WebPortal.dbo.CountrySourceType cst
				WHERE CountryId = cst.CountryId
				) AS source
				ON source.Id = target.Id
			WHEN NOT MATCHED BY target
				THEN
					INSERT (
						[Name],
						[CountryId]
						)
					VALUES (
						 source.Name
						,source.CountryId
		
						);

I tried it using the merge and narrowed down using the where clause but still it doesn't.

答案1

得分: 0

尽量避免MERGE。通常,您可能会遇到性能问题(以及其他问题)。您可以简单地将source添加到临时表中,然后自行执行更新和插入操作。

DROP TABLE IF EXISTS #temp_table;

SELECT Id = Id * (-1)
      , Name
      , (
        SELECT Id
        FROM country c
        WHERE ISNULL(c.Name, '''') = (
                SELECT ISNULL(cs.Name, '''') Name
                FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                WHERE cs.Id = cst.CountryId
                )
            AND ISNULL(c.ContinentName, '''') = (
                SELECT ISNULL(cs.ContinentName, '''') ContinentName
                FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                WHERE cs.Id = cst.CountryId
				)
		) CountryId

INTO #temp_table

FROM [192.xxx.x.xxx].WebPortal.dbo.CountrySourceType cst
WHERE CountryId = cst.CountryId

UPDATE dbo.CountrySourceType 
SET name = B.name
   ,County_id = B.CountryId
FROM dbo.CountrySourceType  A
INNER JOIN #temp_table B
	ON A.[Id] = B.[Id];


INSERT INTO dbo.CountrySourceType ([Name],[CountryId])
SELECT A.name, A.CountryId
FROM #temp_table A
LEFT JOIN dbo.CountrySourceType B
	ON A.[Id] = B.[Id]
WHERE B.[Id] IS NULL;

INSERT INTO dbo.CountrySourceType ([Name],[CountryId])
SELECT A.name, A.CountryId
FROM #temp_table A
LEFT JOIN dbo.CountrySourceType B
    ON A.[Name] = B.[Name]
	AND A.[CountryId] = B.[CountryId]
WHERE B.[Id] IS NULL;
英文:

Try to avoid MERGE. Generally, you may have performances issues (among the other issues). You can simply add the source in a temporary table and just perform the update and insert by yourself.

DROP TABLE IF EXISTS #temp_table;

SELECT Id = Id * (- 1)
      , Name
      , (
        SELECT Id
        FROM country c
        WHERE ISNULL(c.Name, '') = (
                SELECT ISNULL(cs.Name, '') Name
                FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                WHERE cs.Id = cst.CountryId
                )
            AND ISNULL(c.ContinentName, '') = (
                SELECT ISNULL(cs.ContinentName, '') ContinentName
                FROM [192.xxx.x.xxx].WebPortal.dbo.Country cs
                WHERE cs.Id = cst.CountryId
				)
		) CountryId

INTO #temp_table

FROM [192.xxx.x.xxx].WebPortal.dbo.CountrySourceType cst
WHERE CountryId = cst.CountryId

UPDATE dbo.CountrySourceType 
SET name = B.name
   ,County_id = B.CountryId
FROM dbo.CountrySourceType  A
INNER JOIN #temp_table B
	ON A.[Id] = B.[Id];


INSERT INTO dbo.CountrySourceType ([Name],[CountryId])
SELECT A.name, A.CountryId
FROM #temp_table A
LEFT JOIN dbo.CountrySourceType B
	ON A.[Id] = B.[Id]
WHERE B.[Id] IS NULL;

INSERT INTO dbo.CountrySourceType ([Name],[CountryId])
SELECT A.name, A.CountryId
FROM #temp_table A
LEFT JOIN dbo.CountrySourceType B
    ON A.[Name] = B.[Name]
	AND A.[CountryId] = B.[CountryId]
WHERE B.[Id] IS NULL;

huangapple
  • 本文由 发表于 2023年4月11日 13:58:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/75982773.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定