创建存储过程时‘with’关键字附近语法错误的问题求助
解决MERGE语句中WITH关键字附近的语法错误问题
看起来你遇到的语法错误主要来自两个核心问题:OPENJSON的WITH子句定义不完整,以及MERGE语句的核心逻辑结构缺失。我帮你梳理并修正了代码,同时详细解释问题根源:
错误根源分析
- 截断的字段类型声明:你提供的代码里
Memo V...明显是被截断了,SQL Server无法识别不完整的数据类型定义,这直接触发了WITH关键字附近的语法报错。 - 不完整的MERGE结构:MERGE语句必须包含匹配条件、至少一个操作分支(UPDATE/INSERT/DELETE),你的代码只写到了
AS Source就中断了,缺少核心的逻辑分支,这也是语法错误的重要原因。
修正后的完整存储过程
CREATE PROCEDURE usp_PaymentRecommendationsInsertUpdate @PaymentRecommendationsJson NVARCHAR(MAX) AS BEGIN SET NOCOUNT ON; -- 抑制影响行数消息,提升执行体验 MERGE INTO PaymentRecommendations AS Target USING ( SELECT ClaimId, CoverageTypeId, Payee, IndemnityPmtRequestAmnt, ExpensePaymentRequestAmnt, RequestDate, Memo, CheckNumber, IssueDate, CreatedOn, CreatedBy, ModifiedOn, ModifiedBy FROM OPENJSON(@PaymentRecommendationsJson) WITH ( ClaimId BIGINT, CoverageTypeId SMALLINT, Payee VARCHAR(256), IndemnityPmtRequestAmnt MONEY, ExpensePaymentRequestAmnt MONEY, RequestDate DATETIME, Memo VARCHAR(MAX), -- 补全完整的数据类型,可根据实际表结构调整长度 CheckNumber VARCHAR(50), -- 示例长度,按需修改 IssueDate DATETIME, CreatedOn DATETIME, CreatedBy VARCHAR(128), ModifiedOn DATETIME, ModifiedBy VARCHAR(128) ) ) AS Source -- 关键:定义匹配规则(这里假设ClaimId+CoverageTypeId是联合唯一键,需根据你的表主键调整) ON Target.ClaimId = Source.ClaimId AND Target.CoverageTypeId = Source.CoverageTypeId -- 匹配到现有记录则执行更新 WHEN MATCHED THEN UPDATE SET Target.Payee = Source.Payee, Target.IndemnityPmtRequestAmnt = Source.IndemnityPmtRequestAmnt, Target.ExpensePaymentRequestAmnt = Source.ExpensePaymentRequestAmnt, Target.RequestDate = Source.RequestDate, Target.Memo = Source.Memo, Target.CheckNumber = Source.CheckNumber, Target.IssueDate = Source.IssueDate, Target.ModifiedOn = Source.ModifiedOn, Target.ModifiedBy = Source.ModifiedBy -- 无匹配记录则插入新数据 WHEN NOT MATCHED BY TARGET THEN INSERT ( ClaimId, CoverageTypeId, Payee, IndemnityPmtRequestAmnt, ExpensePaymentRequestAmnt, RequestDate, Memo, CheckNumber, IssueDate, CreatedOn, CreatedBy, ModifiedOn, ModifiedBy ) VALUES ( Source.ClaimId, Source.CoverageTypeId, Source.Payee, Source.IndemnityPmtRequestAmnt, Source.ExpensePaymentRequestAmnt, Source.RequestDate, Source.Memo, Source.CheckNumber, Source.IssueDate, Source.CreatedOn, Source.CreatedBy, Source.ModifiedOn, Source.ModifiedBy ) -- 目标表存在但JSON中没有的记录,执行删除 WHEN NOT MATCHED BY SOURCE THEN DELETE; END GO
重要注意事项
- 匹配条件要精准:确保
ON子句使用的是表的主键或唯一约束,否则会出现重复更新/插入的逻辑错误。 - 字段类型需一致:
OPENJSON WITH中的数据类型必须和PaymentRecommendations表的字段类型完全匹配,避免隐式转换导致的异常。 - 删除逻辑的风险:
WHEN NOT MATCHED BY SOURCE THEN DELETE会删除所有不在JSON中的表记录,如果只需要删除特定范围的记录(比如某个Claim下的),需要在USING子查询中添加过滤条件,或者调整匹配规则。 - 自增主键处理:如果你的表有自增ID字段,不要在INSERT列表中包含它,除非你显式执行
SET IDENTITY_INSERT PaymentRecommendations ON。
内容的提问来源于stack exchange,提问作者Kaishu
相关产品推荐
相关产品推荐

