sql-server - 在 MERGE INTO 语句中使用 ON 的语法问题

标签 sql-server merge

智能感知错误:

Msg 156, Level 15, State 1, Procedure Location_CVT_Insert, Line 19 [Batch Start Line 2]
Incorrect syntax near the keyword 'ON'.

存储过程代码:

DROP PROCEDURE IF EXISTS [dbo].[Location_CVT_Insert]
GO

CREATE PROCEDURE [dbo].[Location_CVT_Insert]
     (@Location_NotificationJson NVARCHAR(MAX))
AS 
BEGIN
    MERGE INTO Location_CVT AS C
    USING (SELECT 
               deviceID, lastSeen, locationMapHierarchy, locationCoordinateX, 
               locationCoordinateY, locationCoordinateUnit, geoCoordinateLat,
               geoCoordinateLong, geoCoordinateUnit
           FROM 
               OPENJSON(@Location_NotificationJson)
           WITH 
               (deviceId nchar(17),
                lastSeen varchar(128),
                locationMapHierarchy nvarchar(256),
                locationCoordinateX float,
                locationCoordinateY float,
                locationCoordinateUnit nvarchar(64),
                geoCoordinateLat float,
                geoCoordinateLong float,
                geoCoordinateUnit nvarchar(64)) AS InputJSON) ON (C.deviceId = InputJSON.deviceId)

    WHEN MATCHED THEN
        UPDATE 
            SET C.deviceId = InputJSON.deviceId,
                C.lastSeen = InputJSON.lastSeen,
                C.locationMapHierarchy = InputJSON.locationMapHierarchy,
                C.locationCoordinateX = InputJSON.locationCoordinateX,
                C.locationCoordinateY = InputJSON.locationCoordinateY,
                C.locationCoordinateUnit = InputJSON.locationCoordinateUnit,
                C.geoCoordinateLat = InputJSON.geoCoordinateLat,
                C.geoCoordinateLong = InputJSON.geoCoordinateLong,
                C.geoCoordinateUnit = InputJSON.geoCoordinateUnit

    WHEN NOT MATCHED THEN
        INSERT (deviceId, lastSeen, locationMapHierarchy, 
                locationCoordinateX, locationCoordinateY, 
                locationCoordinateUnit, geoCoordinateLat, 
                geoCoordinateLong, geoCoordinateUnit)
        VALUES (InputJSON.deviceId, InputJSON.lastSeen, InputJSON.locationMapHierarchy, 
                InputJSON.locationCoordinateX, InputJSON.locationCoordinateY, 
                InputJSON.locationCoordinateUnit, InputJSON.geoCoordinateLat, 
                InputJSON.geoCoordinateLong, InputJSON.geoCoordinateUnit);
END

看来 ON 语句是问题所在。我想从 JSON 对象 (SQL Server 2016) 中进行选择,如果我的 Location_CVT 表中的设备 ID 存在匹配项,则更新此条目,否则插入新记录。

我正在尝试执行类似于以下示例的操作。

MERGE INTO Person AS P
USING (
    SELECT *
    FROM  OPENJSON(@json)
          WITH (id int, firstName nvarchar(50), lastName nvarchar(50),
                age int, dateOfBirth datetime2) InputJSON
    ON (P.id = InputJSON.id)
WHEN MATCHED THEN
    UPDATE SET P.firstName = InputJSON.firstName,
               P.lastName = InputJSON.lastName,
               P.age = InputJSON.age,
               P.dateOfBirth = InputJSON.dateOfBirth
WHEN NOT MATCHED THEN
    INSERT (firstName, lastName, age, dateOfBirth)
    VALUES (InputJSON.firstName, InputJSON.lastName, InputJSON.age, 
            InputJSON.dateOfBirth);

来源:https://www.codeproject.com/Articles/1087995/Inserting-JSON-Text-into-SQL-Server-Table

最佳答案

当您的括号跨越多行时,如果您确保左括号和右括号具有一致的缩进,那么问题就会变得更加清晰(至少对我来说是这样)。

MERGE INTO Location_CVT AS C
USING 
(   SELECT 
        deviceID, lastSeen, locationMapHierarchy, locationCoordinateX, 
        locationCoordinateY, locationCoordinateUnit, geoCoordinateLat,
        geoCoordinateLong, geoCoordinateUnit
    FROM 
        OPENJSON(@Location_NotificationJson)
    WITH 
        (   deviceId nchar(17),
            lastSeen varchar(128),
            locationMapHierarchy nvarchar(256),
            locationCoordinateX float,
            locationCoordinateY float,
            locationCoordinateUnit nvarchar(64),
            geoCoordinateLat float,
            geoCoordinateLong float,
            geoCoordinateUnit nvarchar(64)
        ) AS InputJSON
)   ------------------------------------------------- ISSUE IS HERE
    ON (C.deviceId = InputJSON.deviceId)        
WHEN MATCHED THEN
    UPDATE 
        SET C.deviceId = InputJSON.deviceId,
            C.lastSeen = InputJSON.lastSeen,
            C.locationMapHierarchy = InputJSON.locationMapHierarchy,
            C.locationCoordinateX = InputJSON.locationCoordinateX,
            C.locationCoordinateY = InputJSON.locationCoordinateY,
            C.locationCoordinateUnit = InputJSON.locationCoordinateUnit,
            C.geoCoordinateLat = InputJSON.geoCoordinateLat,
            C.geoCoordinateLong = InputJSON.geoCoordinateLong,
            C.geoCoordinateUnit = InputJSON.geoCoordinateUnit

正如您现在可以看到的,您用于源的子查询没有别名。应该是:

MERGE INTO Location_CVT AS C
USING 
(   SELECT 
        deviceID, lastSeen, locationMapHierarchy, locationCoordinateX, 
        locationCoordinateY, locationCoordinateUnit, geoCoordinateLat,
        geoCoordinateLong, geoCoordinateUnit
    FROM 
        OPENJSON(@Location_NotificationJson)
    WITH 
        (   deviceId nchar(17),
            lastSeen varchar(128),
            locationMapHierarchy nvarchar(256),
            locationCoordinateX float,
            locationCoordinateY float,
            locationCoordinateUnit nvarchar(64),
            geoCoordinateLat float,
            geoCoordinateLong float,
            geoCoordinateUnit nvarchar(64)
        ) AS InputJSON
) AS InputJSON                              -- ALIAS ADDED HERE
    ON (C.deviceId = InputJSON.deviceId)    
WHEN MATCHED THEN
    UPDATE 
        SET C.deviceId = InputJSON.deviceId,
            C.lastSeen = InputJSON.lastSeen,
            C.locationMapHierarchy = InputJSON.locationMapHierarchy,
            C.locationCoordinateX = InputJSON.locationCoordinateX,
            C.locationCoordinateY = InputJSON.locationCoordinateY,
            C.locationCoordinateUnit = InputJSON.locationCoordinateUnit,
            C.geoCoordinateLat = InputJSON.geoCoordinateLat,
            C.geoCoordinateLong = InputJSON.geoCoordinateLong,
            C.geoCoordinateUnit = InputJSON.geoCoordinateUnit

关于sql-server - 在 MERGE INTO 语句中使用 ON 的语法问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45619694/

相关文章:

sql-server - SQL Server bacpac 在最新更新中本地导入失败(在线索引操作只能在 SQL Server 企业版中执行)

mysql - 按日期加入 SQL 查询

r - 在 R 中合并多个数据框

forms - 合并 2 个 pdf 文件并保留表格

git - 将 2 个分支 merge 到两个分支之一或新分支中

sql-server - T-SQL 将行连接成字符串

sql-server - 将 dplyr 与数据库一起使用,无需创建显式 DBI 对象

sql - 缺少某些月份时按年份和日期订购 dt

json - 如何使用 jq 合并相同结构的嵌套 json 文件

Git 将一个分支 merge 到另一个分支是双向 merge 吗?