Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

insertion in a self referenced table

Tags:

sql

sql-server

If I have a table

Table
{
ID int primary key identity,
ParentID int not null foreign key references Table(ID)
}

how does one insert first row into a table?

From a business logic point of view not null constraint on ParentID should not be dropped.

like image 663
Nezreli Avatar asked Nov 10 '12 09:11

Nezreli


People also ask

What is self referencing table?

Self-referencing table is a table that is a parent and a dependent in the same referential constraint. I. e. in such tables a foreign key constraint can reference columns within the same table.

How do you add a insert to a table?

Basic INSERT syntax Here is the basic syntax for adding rows to a table in SQL: INSERT INTO table_name (column1, column2, column3,etc) VALUES (value1, value2, value3, etc); The first line of code uses the INSERT statement followed by the name of the table you want to add the data to.

What is a referenced table?

Referenced Tables allow a category's or case. definition's index fields to reference data in an external database. This provides a convenient way to link an index field to a database table from another system.


2 Answers

In SQL Server, a simple INSERT will do:

create table dbo.Foo
(
ID int primary key identity,
ParentID int not null foreign key references foo(ID)
)
go

insert dbo.Foo (parentId) values (1)

select * from dbo.Foo

results in

    ID          ParentID
----------- -----------
    1           1

If you're trying to insert a value that will be different from your identity seed, the insertion will fail.

UPDATE:

The question is not too clear on what the context is (i.e. is the code supposed to work in a live production system or just a DB setup script) and from the comments it seems hard-coding the ID might not be an option. While the code above should normally work fine in the DB initialization scripts where the hierarchy root ID might need to be known and constant, in case of a forest (several roots with IDs not known in advance) the following should work as intended:

create table dbo.Foo
(
ID int primary key identity,
ParentID int not null foreign key references foo(ID)
)
go

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))

Then one could query the last identity as usual (SCOPE_IDENTITY, etc.). To address @usr's concerns, the code is in fact transactionally safe as the following example demonstrates:

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))

select * from dbo.Foo

select IDENT_CURRENT('dbo.Foo')
begin transaction   
    insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))
    rollback

select IDENT_CURRENT('dbo.Foo')

insert dbo.Foo (parentId) values (IDENT_CURRENT('dbo.Foo'))

select * from dbo.Foo

The result:

ID          ParentID
----------- -----------
1           1
2           2
3           3

currentIdentity
---------------------------------------
3

currentIdentity
---------------------------------------
4

ID          ParentID
----------- -----------
1           1
2           2
3           3
5           5
like image 155
Serge Belov Avatar answered Sep 27 '22 20:09

Serge Belov


If you need to use an explicit value for the first ID, when you insert your first record, you can disable the checking of the IDENTITY value (see: MSDN: SET IDENTITY_INSERT (Transact-SQL)).

Here's an example that illistrates this:

CREATE TABLE MyTable
(
  ID int PRIMARY KEY IDENTITY(1, 1),
  ParentID int NOT NULL,
  CONSTRAINT MyTable_ID FOREIGN KEY (ParentID) REFERENCES MyTable(ID)
);

SET IDENTITY_INSERT MyTable ON;
INSERT INTO MyTable (ID, ParentID)
VALUES (1, 1);
SET IDENTITY_INSERT MyTable OFF;

WHILE @@IDENTITY <= 5
BEGIN
    INSERT INTO MyTable (ParentID)
    VALUES (@@IDENTITY);
END;

SELECT *
  FROM MyTable;

IF OBJECT_ID('MyTable') IS NOT NULL
    DROP TABLE MyTable;
like image 44
Alexander Avatar answered Sep 27 '22 18:09

Alexander