【问题标题】:'An explicit value for the identity column can only be specified...' during Merge“只能指定标识列的显式值......”在合并期间
【发布时间】:2016-01-25 20:50:18
【问题描述】:

有很多问题可以涵盖此错误,但我遇到的问题是:

A) 我目前正在进行合并(使用插入)

B) 我没有明确设置标识列!

我的存储过程(表名和属性被混淆):

表定义

CREATE TABLE MyTable (
    [ID] BIGINT IDENTITY(1, 1) NOT NULL,
    [Value] NVARCHAR (256) NOT NULL,
    [Property] NVARCHAR (256) NOT NULL,
    CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED ([ID] ASC),
    CONSTRAINT [IX_MyTable] UNIQUE NONCLUSTERED ([Value] ASC)
);

存储过程定义

CREATE TYPE TempType as Table (
    [TempValue] nvarchar(256) NOT NULL,
    [TempProperty] nvarchar(256) NOT NULL,
);
GO

CREATE PROCEDURE [Name]
    @Source TempType READONLY
AS
BEGIN
    MERGE [MyTable] as target
    USING (SELECT * FROM @Source) as source (TempValue, TempProperty)
    ON (target.Value = source.TempValue)
    WHEN MATCH THEN
        UPDATE SET Value = source.TempValue, Property = source.TempProperty
    WHEN NOT MATCHED THEN
        INSERT ([Value], [Property])
        VALUES (source.TempValue, source.TempProperty)
        OUTPUT deleted.*, $action, inserted.* INTO [MyTable];

END

据我所知,我没有在任何地方明确指定 IDENTITY 列。我指定了一个UNIQUE-ly 约束列。

最后,与错误所说的相反,指定 IDENTITY_INSERT ON 没有任何作用。

编辑:我还应该指定,我在通过 C# 从 .dacpac 部署时遇到此错误。

【问题讨论】:

  • OUTPUT .... INTO [MyTable] 对我来说似乎插入了一个身份列
  • 它正在插入一个新行并让表格处理它,对吗?我可以在其他地方直接(而不是合并)插入表格中。我还应该澄清一下,我不确定该输出部分在做什么。我从 MSFT 的一个示例中复制的,没有它,MERGE 似乎无法工作。有没有办法去掉它或去掉插入物?
  • 您似乎根本不需要OUTPUT
  • 啊,我想我明白了。我可以从 OUTPUT 声明中删除表(或整个 OUTPUT),它就可以工作了!之前测试时,我一直在删除 OUTPUT 但没有删除“INTO MyTable”。如果您想添加作为答案,我会接受。非常感谢!
  • 这并不是一个真正的答案,只是一个有根据的猜测

标签: sql sql-server merge sql-server-2012 sql-merge


【解决方案1】:

我会简单地摆脱 MERGE 语句(设计上有很多问题)并使用如下简单的插入语句:

CREATE PROCEDURE [Name]
    @Source TempType READONLY
AS
BEGIN
  SET NOCOUNT ON;

    INSERT INTO [MyTable] ([Value], [Property])
    SELECT s.TempValue, s.TempProperty 
    FROM @Source s
    WHERE EXISTS (SELECT 1 
                  FROM [MyTable]  
                  WHERE Value = s.TempValue)

END

要了解有关 MERGE 语句的问题,请查看这篇文章 Use Caution with SQL Server's MERGE Statement

由于您已在 Merge 语句中添加了更新,现在我还将添加一条更新语句并将更新包装并插入到一个事务中,但我仍然不建议使用合并语句。

CREATE PROCEDURE [Name]
    @Source TempType READONLY
AS
BEGIN
  SET NOCOUNT ON;


BEGIN TRANSACTION;

     UPDATE T
       SET T.[Property] = S.[Property]
     FROM [MyTable] T 
     INNER JOIN @Source s ON T.Value = s.TempValue



    INSERT INTO [MyTable] ([Value], [Property])
    SELECT s.TempValue, s.TempProperty 
    FROM @Source s
    WHERE NOT EXISTS (SELECT 1 
                      FROM [MyTable]  
                      WHERE Value = s.TempValue)


COMMIT TRANSACTION;

END

【讨论】:

  • 我不需要INSERTUPDATE 吗?
  • @NateDiamond 你实际上并没有更新任何东西。当它们与您的目标表匹配时,您正在插入这些行,所以这也很奇怪
  • @NateDiamond 正如 Lamak 已经提到的那样,您的 Merge 语句仅在根据您定义的条件存在匹配行时插入,您的合并语句中根本没有更新,附带说明如果您需要并更新,请在上述解决方案中添加单独的更新语句,并在 ONE TRANSACTION 中对它们进行扭曲,但我仍然会远离 Merge 语句。
  • 哎呀!不知何故,更新部分未包含在帖子中。固定的!更糟糕的是我已经喝过咖啡了:|
  • @NateDiamond 现在看看我的解决方案,就像我之前说过的,我会远离 Merge 声明。
猜你喜欢
  • 2013-06-05
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-08
  • 2011-01-01
  • 1970-01-01
  • 2016-10-21
  • 1970-01-01
相关资源
最近更新 更多