Skip Navigation Links
Home
Articles
SQL Server 2012
SQL Server 2014
SQL Server 2016
FAQ
Practice Test
Tip of the Day : Beals Conjecture - A Search for Counterexamples Using SQL Server
Error Messages
Home > SQL Server Error Messages > Msg 332 - The target table '<Table Name>' of the OUTPUT INTO clause cannot be on either side of a (primary key, foreign key) relationship. Found reference constraint '<Primary Key or Foreign Key Constraint Name>'.
SQL Server Error Messages - Msg 332 - The target table '<Table Name>' of the OUTPUT INTO clause cannot be on either side of a (primary key, foreign key) relationship. Found reference constraint '<Primary Key or Foreign Key Constraint Name>'.

Error Message

Server: Msg 332, Level 16, State 1, Line 1
The target table '<Table Name>' of the OUTPUT INTO 
clause cannot be on either side of a (primary key, 
foreign key) relationship. Found reference constraint 
'<Primary Key or Foreign Key Constraint Name>'.

Causes

The OUTPUT clause, introduced in SQL Server 2005, returns information from, or expressions based on, each row affected by an INSERT, UPDATE, DELETE or MERGE statement.

These results can be returned to the processing application for use in such things as confirmation messages, archiving, and other such application requirements. The results can also be inserted into a table or table variable. Additionally, you can capture the results of an OUTPUT clause in a nested INSERT, UPDATE, DELETE, or MERGE statement, and insert those results into a target table or view.

One of the restrictions when using the OUTPUT clause is that if the result of the OUTPUT clause is inserted into a table, the table cannot participate on either side of a FOREIGN KEY constraint; otherwise this error message will be encountered.

To illustrate how this error is generated, given the following tables structures:

CREATE TABLE [dbo].[Product] (
    [ProductID]        INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
    [ProductName]      VARCHAR(100) NOT NULL,
    [UnitPrice]        MONEY,
    [Quantity]         INT
)

CREATE TABLE [dbo].[ProductPriceHistory] (
    [ProductPriceHistoryID]  INT NOT NULL IDENTITY(1, 1) PRIMARY KEY,
    [ProductID]              INT NOT NULL,
    [OldUnitPrice]           MONEY,
    [NewUnitPrice]           MONEY,
    [ChangeDate]             DATETIME DEFAULT (GETDATE())
)

ALTER TABLE [dbo].[ProductPriceHistory]
ADD CONSTRAINT [FK_ProductPriceHistory_Product]
FOREIGN KEY ( [ProductID] ) REFERENCES [dbo].[Product] ( [ProductID] )

As a sales promotion within a company, the price needs to be decreased by 10% for all products where the current price is greater than or equal to $1,000.00. For each product whose price was decreased, the old price and the new price need to be inserted in the product price history table.

In fulfilling this requirement, the following UPDATE statement which includes the OUTPUT INTO clause is executed.

UPDATE [dbo].[Product]
SET [UnitPrice] = [UnitPrice] * 0.9
OUTPUT [inserted].[ProductID], [deleted].[UnitPrice], 
       [inserted].[UnitPrice], GETDATE() INTO [dbo].[ProductPriceHistory]
WHERE [UnitPrice] >= 1000

But since the target table, in this case the [dbo].[ProductPriceHistory] table, has a foreign key constraint against the [dbo].[Product] table, the following error message is encountered:

Msg 332, Level 16, State 1, Line 1
The target table 'dbo.ProductPriceHistory' of the OUTPUT INTO clause cannot be on either side of a
(primary key, foreign key) relationship.  Found reference constraint
'FK_ProductPriceHistory_Product'.

Solution / Work Around:

As mentioned earlier, and as the message suggests, the target table of the OUTPUT INTO clause cannot participate on either side of a FOREIGN KEY constraint. To overcome this restriction, one thing that can be done is to insert the updated products together with the old and new prices into a temporary table or a table variable. Then after the UPDATE statement, the updated product information can now be inserted into the product price history table.

The following script can be used to replace the UPDATE statement earlier which inserts all updated products together with their old and new unit price after the UPDATE operation.

DECLARE @ProductPriceHistory TABLE (
    [ProductID]          INT,
    [OldUnitPrice]       MONEY,
    [NewUnitPrice]       MONEY
)
 
UPDATE [dbo].[Product]
SET [UnitPrice] = [UnitPrice] * 0.9
OUTPUT [inserted].[ProductID], [deleted].[UnitPrice], [inserted].[UnitPrice]
INTO @ProductPriceHistory
WHERE [UnitPrice] >= 1000
 
INSERT INTO [dbo].[ProductPriceHistory] ( [ProductID], [OldUnitPrice], [NewUnitPrice], [ChangeDate] )
SELECT [ProductID], [OldUnitPrice], [NewUnitPrice], GETDATE()
FROM @ProductPriceHistory

The first part of the script is the declaration of a table variable that will contain the product ID of the products updated together with the old unit price and new unit price. This table variable is then used as the target table for in the OUTPUT INTO clause of the UPDATE statement.

Lastly, all updated products that are now in the table variable can now be inserted to the product price history table without generating this error.

Related Articles :