我在讓 MERGE 陳述句正常作業時遇到問題,最近我開始嘗試使用校驗和。
在下面的玩具示例中,我無法插入(1, 'ANDREW', 334.3)位于暫存表中的這一行。
DROP TABLE TEMP1
DROP TABLE TEMP1_STAGE
-- create table
CREATE TABLE TEMP1
(
[ID] INT,
[NAME] VARCHAR(55),
[SALARY] FLOAT,
[SCD] INT
)
-- create stage
CREATE TABLE TEMP1_STAGE
(
[ID] INT,
[NAME] VARCHAR(55),
[SALARY] FLOAT,
[SCD] INT
)
-- insert vals into stage
INSERT INTO TEMP1_STAGE (ID, NAME, SALARY)
VALUES
(1, 'ANDREW', 333.3),
(2, 'JOHN', 555.3),
(3, 'SARAH', 444.3)
-- insert stage table into main table
INSERT INTO TEMP1
SELECT *
FROM TEMP1_STAGE;
-- clean up stage table
TRUNCATE TABLE TEMP1_STAGE;
-- put some new values in the stage table
INSERT INTO TEMP1_STAGE (ID, NAME, SALARY)
VALUES
(1, 'ANDREW', 334.3),
(4, 'CARL', NULL)
-- CHECKSUMS
update TEMP1_STAGE
set SCD = binary_checksum(ID, NAME, SALARY);
update TEMP1
set SCD = binary_checksum(ID, NAME, SALARY);
-- run merge
MERGE TEMP1 AS TARGET
USING TEMP1_STAGE AS SOURCE
-- match
ON (SOURCE.[ID] = TARGET.[ID])
WHEN NOT MATCHED BY TARGET
THEN INSERT (
[ID], [NAME], [SALARY], [SCD]) VALUES (
SOURCE.[ID], SOURCE.[NAME], SOURCE.[SALARY], SOURCE.[SCD]);
-- the value: (1, 'ANDREW', 334.3) is not merged in
SELECT * FROM TEMP1;
我如何在 MERGE 中利用校驗和來發揮我的優勢?
uj5u.com熱心網友回復:
您的問題是NOT MATCHED條件僅考慮條件中ID指定的值ON。
如果您想要重復但不同的記錄,請包含SCD到ON條件中。
如果(更有可能)您的意圖是使用 new 更新記錄 ID = 1 SALARY,您將需要添加一個WHEN MATCHED AND SOURCE.SCD <> TARGET.SCD THEN UPDATE ...子句。
也就是說,`binary_checksum()' 函式回傳的 32 位 int 值不足以區分以避免沖突和不必要的錯過更新。看看 HASHBYTES 吧。請參閱Binary_Checksum 與 HashBytes 函式。
即使那樣也可能不會產生您預期的性能提升。假設您必須為每個更新周期計算臨時表中所有記錄的哈希值,您可能會發現在更新前比較每個可能不同的欄位更簡單。就像是:
WHEN MATCHED AND (SOURCE.NAME <> TARGET.NAME OR SOURCE.SALARY <> TARGET.SALARY)
THEN UPDATE ...
即便如此,您也需要小心潛在的 NULL 值和 COLLATION。雙方NULL <> 50000.00并'Andrew' <> 'ANDREW'可能不會給你你所期望的結果。僅編碼可能是最簡單和最可靠的WHEN MATCHED THEN UPDATE ...。
最后,我建議使用DECIMAL而不是FLOATfor Salary。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/340095.html
標籤:sql sql-server 查询语句
上一篇:使用標量值函式添加列值
