There is a Microsoft Connect suggestion requesting a function to do exactly this:
keyword/function for INSERTING a self referencing identity
It is still marked as "Active", however, there is a comment from Microsoft -- February of 2015 -- saying that they are closing it but might consider re-opening it in the future. So, I doubt it will get implemented.
On the other hand, depending on what version of SQL Server is being used, it might be possible to use a Sequence instead. In fact, there is a note on that linked MSDN page, under the Limitations section, which states:
If there are multiple instances of the NEXT VALUE FOR function specifying the same sequence generator within a single Transact-SQL statement, all those instances return the same value for a given row processed by that Transact-SQL statement. This behavior is consistent with the ANSI standard.
With that behavior in mind, we can do the following:
USE [tempdb];
CREATE SEQUENCE dbo.Seq
AS INT
START WITH 1
INCREMENT BY 1;
CREATE TABLE dbo.SelfRefTest
(
[SelfRefTestID] INT NOT NULL
CONSTRAINT [PK_SelfRefTest] PRIMARY KEY
CONSTRAINT [DF_SelfRefTest_SelfRefTestID] DEFAULT (NEXT VALUE FOR dbo.Seq),
[Name] NVARCHAR(50) NOT NULL,
[ParentSelfRefTestID] INT NULL
CONSTRAINT [FK_SelfRefTest_SelfRefTest_SelfRefTestID] FOREIGN KEY
REFERENCES dbo.SelfRefTest(SelfRefTestID)
CONSTRAINT [DF_SelfRefTest_ParentSelfRefTestID] DEFAULT (NEXT VALUE FOR dbo.Seq)
);
INSERT INTO dbo.SelfRefTest ([Name]) VALUES (N'Bob');
INSERT INTO dbo.SelfRefTest ([Name]) VALUES (N'Sally');
SELECT * FROM dbo.SelfRefTest;
INSERT INTO dbo.SelfRefTest ([Name], [ParentSelfRefTestID]) VALUES (N'Sub-Bob', 1);
INSERT INTO dbo.SelfRefTest ([Name], [ParentSelfRefTestID]) VALUES (N'No Parent', NULL);
SELECT * FROM dbo.SelfRefTest;
INSERT INTO dbo.SelfRefTest ([Name], [ParentSelfRefTestID])
VALUES (N'Invalid FK error', 13);
Results of the second SELECT are:
SelfRefTestID Name ParentSelfRefTestID
------------- --------- -------------------
1 Bob 1
2 Sally 2
3 Sub-Bob 1
4 No Parent NULL