在sqlserver中合并 - 语法不正确

时间:2016-05-31 13:34:34

标签: sql sql-server merge

我尝试执行此交易:

GO
BEGIN TRAN;
MERGE A AS t 
USING B AS tmp
ON (t.domain = tmp.domain and t.link=tmp.link) 
WHEN NOT MATCHED BY A
    THEN INSERT(ipVal, domain, dateStart, dateUpdate, dateFinish, link) VALUES(tmp.ipVal, tmp.domain, tmp.dateStart, tmp.dateUpdate, tmp.dateFinish, tmp.link)
WHEN MATCHED 
    THEN UPDATE SET t.dateupdate = tmp.dateupdate
WHEN NOT MATCHED BY B
    THEN UPDATE SET t.datefinish="a"
ROLLBACK TRAN;
GO 

我从here获取此代码,但是当我尝试执行此操作时出现错误:

Incorrect syntax near 'A'

可能是什么问题?

3 个答案:

答案 0 :(得分:6)

根据MSDNWHEN NOT MATCHED分支的简化语法是

   [ WHEN NOT MATCHED [ BY TARGET ] [...]
        THEN <merge_not_matched> ]
    [ WHEN NOT MATCHED BY SOURCE [...]
        THEN <merge_matched> ] [ ...n ]

解决方案是将WHEN NOT MATCHED BY A替换为WHEN NOT MATCHED BY TARGET,将WHEN NOT MATCHED BY B替换为WHEN NOT MATCHED BY SOURCE

TARGETSOURCE是T-SQL关键字而不是占位符。

答案 1 :(得分:0)

我刚刚开始使用MERGE我使用这种语法来理解它:

MERGE A AS target
USING B AS source
ON (target.domain = source.domain and target.link=source.link) 
WHEN NOT MATCHED BY TARGET
    THEN INSERT(ipVal, domain, dateStart, dateUpdate, dateFinish, link)
    VALUES(source.ipVal, source.domain, source.dateStart, source.dateUpdate, source.dateFinish, source.link)
WHEN MATCHED 
    THEN UPDATE SET target.dateupdate = source.dateupdate
WHEN NOT MATCHED BY SOURCE
    THEN UPDATE SET target.datefinish="a"

我知道这是一种不好的做法,但一旦开始 - 有很多帮助。

由于@BogdanSahlean积分TARGETSOURCE是关键字,因此在您确定匹配/不匹配的陈述时需要。

答案 2 :(得分:0)

看起来您正在尝试使用不能转换为日期或日期时间类型的char或varchar类型数据更新日期或日期时间类型列。 &#39;一个&#39;不可转换为日期或日期时间。看看我在下面的第一个和第二个合并。如果你没有提到匹配时或者没有匹配源或目标,默认它会考虑目标。

--DROP TABLE #A;
--DROP TABLE #B;

CREATE TABLE #A
    (
        ipval VARCHAR(50)
    , domain CHAR(5)
    , dateStart DATE
    , dateUpdate DATE
    , dateFinish DATE
    , link VARCHAR(50)
    );

CREATE TABLE #B
    (
        ipval VARCHAR(50)
    , domain CHAR(5)
    , dateStart DATE
    , dateUpdate DATE
    , dateFinish DATE
    , link VARCHAR(50)
    );
INSERT  INTO #B
        ( ipval, domain, dateStart, dateUpdate, dateFinish, link )
VALUES  ( '42.130.239.56'  -- ipval - varchar(50)
            , '.com'  -- domain - char(5)
            , GETDATE()  -- dateStart - date
            , DATEADD(DAY, 1, GETDATE())  -- dateUpdate - date
            , DATEADD(DAY, 5, GETDATE())  -- dateFinish - date
            , 'www.stackoverflow'  -- link - varchar(50)
            ),
        ( '78.188.136.74'  -- ipval - varchar(50)
            , '.com'  -- domain - char(5)
            , GETDATE()  -- dateStart - date
            , DATEADD(DAY, 2, GETDATE())  -- dateUpdate - date
            , DATEADD(DAY, 10, GETDATE())  -- dateFinish - date
            , 'www.msdn'  -- link - varchar(50)
            );

INSERT  INTO #A
        ( ipval, domain, dateStart, dateUpdate, dateFinish, link )
VALUES  ( '30.48.111.20'  -- ipval - varchar(50)
            , '.com'  -- domain - char(5)
            , GETDATE()  -- dateStart - date
            , DATEADD(DAY, 5, GETDATE())  -- dateUpdate - date
            , DATEADD(DAY, 10, GETDATE())  -- dateFinish - date
            , 'www.msdn'  -- link - varchar(50)
            ),
        ( '30.48.111.20'  -- ipval - varchar(50)
            , '.com'  -- domain - char(5)
            , GETDATE()  -- dateStart - date
            , DATEADD(DAY, 5, GETDATE())  -- dateUpdate - date
            , DATEADD(DAY, 10, GETDATE())  -- dateFinish - date
            , 'www.gmail'  -- link - varchar(50)
            );
--First Merge
BEGIN TRAN;
MERGE #A AS T
USING #B AS tmp
ON T.domain = tmp.domain
    AND T.link = tmp.link
WHEN NOT MATCHED BY TARGET THEN
    INSERT ( ipval
            , domain
            , dateStart
            , dateUpdate
            , dateFinish
            , link
            )
    VALUES ( tmp.ipval
            , tmp.domain
            , tmp.dateStart
            , tmp.dateUpdate
            , tmp.dateFinish
            , tmp.link
            )
WHEN MATCHED THEN
    UPDATE SET T.dateUpdate = tmp.dateUpdate
WHEN NOT MATCHED BY SOURCE THEN
    UPDATE SET T.dateFinish =''a'';
COMMIT TRAN;
GO


SELECT  *
FROM    #A;
SELECT  *
FROM    #B;
--Second Merge
BEGIN TRAN;
MERGE #A AS T
USING #B AS tmp
ON T.domain = tmp.domain
    AND T.link = tmp.link
WHEN NOT MATCHED BY TARGET THEN
    INSERT ( ipval
           , domain
           , dateStart
           , dateUpdate
           , dateFinish
           , link
           )
    VALUES ( tmp.ipval
           , tmp.domain
           , tmp.dateStart
           , tmp.dateUpdate
           , tmp.dateFinish
           , tmp.link
           )
WHEN MATCHED THEN
    UPDATE SET T.dateUpdate = tmp.dateUpdate
WHEN NOT MATCHED BY SOURCE THEN
    UPDATE SET T.dateFinish = CAST(GETDATE() AS DATE);
COMMIT TRAN;
GO


SELECT  *
FROM    #A;
SELECT  *
FROM    #B;