'只能指定标识列的显式值...'在合并期间

时间:2015-10-26 16:43:28

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

有很多问题可以解决这个错误,但我遇到的问题是:

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 - 约束列。

最后,与错误所说的相反,指定IDENTITY_INSERT ON不会做任何事情。

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

1 个答案:

答案 0 :(得分:0)

我会简单地删除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语句中添加了更新,现在我还要添加更新语句并将更新包装并插入到一个事务中,但我仍然不建议使用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