简体   繁体   中英

Get Identity of destination table when using **DELETE FROM … OUTPUT … INTO**

I use bellow code to archive old data in ArchiveTable and delete archived data from SourceTable

DELETE FROM SourceTable 
OUTPUT 
    DELETED.[ID], 
    DELETED.[Code],
    DELETED.[Title]
INTO ArchiveTable([OldID], [Code], [Title])
WHERE Condition

Structure of tables:

CREATE TABLE [SourceTable](
    [ID] [INT] IDENTITY(1,1) NOT NULL,
    [Code] [VARCHAR](16) NULL,
    [Title] [NVARCHAR](128) NULL,
    CONSTRAINT [PK_SourceTable] PRIMARY KEY CLUSTERED ([ID] ASC)
) 
GO

CREATE TABLE [ArchiveTable](
    [ID] [INT] IDENTITY(1,1) NOT NULL,
    [OldID] [INT] NOT NULL,
    [Code] [VARCHAR](16) NULL,
    [Title] [NVARCHAR](128) NULL,
    CONSTRAINT [PK_ArchiveTable] PRIMARY KEY CLUSTERED ([ID] ASC)
) 
GO

I need to return deleted records and ArchiveTable.[ID] to application. I change the code like this:

DELETE FROM SourceTable 
OUTPUT 
    DELETED.[ID], 
    DELETED.[Code],
    DELETED.[Title]
INTO ArchiveTable([OldID], [Code], [Title])
OUTPUT DELETED.*
WHERE Condition

This code return deleted records but I don't know how to get ID of ArchiveTable for this records. Look at ArchiveTable structure, It has OldID column that refer to SourceTable.ID and ID column that it is an Identity column of ArchiveTable . I need to ArchiveTable.ID in final result.

You can use a temporary table

CREATE TABLE #DeletedRows(
    [ID] [INT] NOT NULL,
    [Code] [VARCHAR](16) NULL,
    [Title] [NVARCHAR](128) NULL
)

DELETE SourceTable 
OUTPUT 
    DELETED.[ID], 
    DELETED.[Code],
    DELETED.[Title]
INTO #DeletedRows([ID], [Code], [Title])
WHERE Condition

INSERT ArchiveTable([OldID], [Code], [Title])
OUTPUT INSERTED.*
SELECT [ID], [Code], [Title]
FROM #DeletedRows

DROP TABLE #DeletedRows

A variant with a table variable

DECLARE @DeletedRows TABLE(
    [ID] [INT] NOT NULL,
    [Code] [VARCHAR](16) NULL,
    [Title] [NVARCHAR](128) NULL
)

DELETE SourceTable 
OUTPUT 
    DELETED.[ID], 
    DELETED.[Code],
    DELETED.[Title]
INTO @DeletedRows([ID], [Code], [Title])
WHERE Condition

INSERT ArchiveTable([OldID], [Code], [Title])
OUTPUT INSERTED.*
SELECT [ID], [Code], [Title]
FROM @DeletedRows

I found an interesting variant using DML with OUTPUT in SP and INSERT...EXEC... after that:

Test tables:

CREATE TABLE TestTable(
  ID int NOT NULL PRIMARY KEY,
  Title varchar(10) NOT NULL
)

CREATE TABLE TestTableLog(
  LogID int NOT NULL IDENTITY,
  OperType char(1) NOT NULL,
  CHECK(OperType IN('I','U','D')),
  ID int NOT NULL,
  Title varchar(10) NOT NULL
)

DML procedures:

CREATE PROC InsTestTable
  @ID int,
  @Title varchar(10)
AS

  INSERT TestTable(ID,Title)
  OUTPUT inserted.ID,inserted.Title,'I' OperType
  VALUES(@ID,@Title)

GO

CREATE PROC UpdTestTable
  @ID int,
  @Title varchar(10)
AS

  UPDATE TestTable
  SET
    Title=@Title
  OUTPUT inserted.ID,inserted.Title,'U' OperType
  WHERE ID=@ID

GO

CREATE PROC DelTestTable
  @ID int
AS

  DELETE TestTable
  OUTPUT deleted.ID,deleted.Title,'D' OperType
  WHERE ID=@ID

GO

Tests:

-- insert test
INSERT TestTableLog(ID,Title,OperType)
EXEC InsTestTable 1,'A'

INSERT TestTableLog(ID,Title,OperType)
EXEC InsTestTable 2,'B'

INSERT TestTableLog(ID,Title,OperType)
EXEC InsTestTable 3,'C'

-- update test
INSERT TestTableLog(ID,Title,OperType)
EXEC UpdTestTable 2,'BBB'

-- delete test
INSERT TestTableLog(ID,Title,OperType)
EXEC DelTestTable 3
GO

-- show resutls
SELECT *
FROM TestTableLog

Maybe it'll be interesting to someone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM