【问题标题】:merge in sqlserver - incorrect syntax在 sqlserver 中合并 - 语法不正确
【发布时间】:2016-09-29 13:26:22
【问题描述】:

我尝试执行此交易:

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'

可能是什么问题?

【问题讨论】:

  • 一个可以理解的错误,因为您链接到的 Technet 页面使用 TargetSource 作为示例表的名称,因此将它们与 TARGETSOURCE 关键字混合在一起。跨度>

标签: sql sql-server merge


【解决方案1】:

根据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 关键字而不是占位符。

【讨论】:

    【解决方案2】:

    一个我刚开始用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 是关键字,在确定匹配/不匹配语句时需要。

    【讨论】:

      【解决方案3】:

      看起来您正在尝试使用无法转换为日期或日期时间类型的 char 或 varchar 类型数据更新日期或日期时间类型列。 'a' 不能转换为日期或日期时间。看看我下面的第一个和第二个 Merge。如果你没有提到匹配时或不匹配时源或目标,默认情况下它考虑目标。

      --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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-18
        • 2020-10-30
        • 2016-03-20
        相关资源
        最近更新 更多