Как вставить строку в таблицу с внешним ключом к себе? - PullRequest
3 голосов
/ 22 мая 2011

У меня есть таблица , которая имеет внешний ключ для себя. Столбец parentid является внешним ключом, и он не может быть NULL.

если я сделаю INSERT INTO mytable(name) VALUES('name'), значит, он не может вставить NULL в parentid . НО, какое значение я могу установить, если строка еще не вставлена?!

Как мне написать скрипт, который добавит строку в эту таблицу?

Спасибо

Ответы [ 7 ]

5 голосов
/ 23 мая 2011

Удалите ограничение NOT NULL, так как это неуместное ограничение. Если у вас нет ParentId, тогда значение равно NULL и должно быть разрешено. Создание фиктивной строки только для того, чтобы иметь фиктивную парентиду, создает ненужные зависимости.

5 голосов
/ 22 мая 2011

Подвох: имейте фиктивный ряд с фиктивным ключом, скажем, 99999. Вставьте с этим как FK, а затем измените FK на его реальное значение.И сделай это в транзакции.

2 голосов
/ 26 апреля 2012

Отключить ответственный FK. Затем сделайте вставку Затем выполните обновление с новым (сгенерированным?) PK-ID в поле Self-FK-Field. Затем включите FK обратно.

Как и так:

ALTER TABLE [Client] NOCHECK CONSTRAINT [FK_Client_MainClient]
INSERT INTO Client VALUES ...
@ClientID = SCOPE_IDENTITY()
IF @IsMainClient=1  
BEGIN
    UPDATE [Client] 
    SET MainClientID = @ClientID 
    WHERE ClientID = @ClientID 
END 
ALTER TABLE [Relatie] WITH CHECK CHECK CONSTRAINT [FK_Relatie_Relatie]
2 голосов
/ 23 мая 2011

Как сделать фиктивную строку с id и parentid равными -1:

CREATE TABLE mytable(
    id int NOT NULL IDENTITY,
    parentid int  NOT NULL,

    PRIMARY KEY (id),
    FOREIGN KEY (parentid) REFERENCES mytable(id)
)  ;


SET IDENTITY_INSERT mytable ON ;      <-- this allows you to insert the 
INSERT INTO mytable(id, parentid)     <-- auto incremented identity field
    VALUES (-1, -1);
SET IDENTITY_INSERT mytable OFF ;

SELECT * FROM mytable ;

| id | parentid |
| -1 | -1       |

Если у вас есть много данных из других таблиц, которые вы хотите перенести в эту таблицу,вы можете установить для переменной IDENTITY_INSERT значение ON, вставить данные и затем снова установить для них значение OFF.

Но, как говорили другие, было бы лучше просто удалить ограничение NOT NULL из поля parentid.

1 голос
/ 23 мая 2011

Из того, что я понял, у вас уже есть идентификатор перед вставкой, и вы не можете вставить его, потому что поле идентификации не позволяет вам.

Как вы упомянули в комментарии:

в 1 таблице у меня есть строки 34 'name1' 34, 35 'name2' 34 (id, name, parentid) и я хочу скопировать их в другую таблицу

Первый стол

create table Table1
(
    id int not null primary key,
    name varchar(20) not null,
    parentId int not null
)

insert Table1
values
    (34, 'name1', 34),
    (35, 'name2', 34)

Второй стол:

create table Table2
(
    id int identity(1, 1) primary key,
    name varchar(20) not null,
    parentId int not null foreign key references Table2(id)
)

Копирование данных из первой таблицы во вторую:

set identity_insert Table2 on

insert Table2(id, name, parentId)
select *
from  Table1

set identity_insert Table2 on

[Update]

Если вторая таблица уже имеет значения, то:

alter table Table2
    add oldId int null

alter table Table2
    alter column parentId int null
go

insert Table2(name, oldId)
select name, id
from  Table1

update tt3
set parentId = tt2.id
from Table2 tt3
    join Table1 tt1 on
        tt1.id = tt3.oldId
    join Table2 tt2 on
        tt1.parentId = tt2.oldId

alter table Table2
    drop column oldId

alter table Table2
    alter column parentId int not null
1 голос
/ 23 мая 2011

Вы можете изменить столбец, чтобы разрешить нулевое значение, затем установить fk на новый идентификатор и снова включить не нулевое значение.

Это должно работать, хотя, может быть, есть лучший способ

CREATE TABLE mytable
(
 id int IDENTITY(1,1) primary key,
 name varchar(50) not null,
 parentid int not null
)
go
alter table mytable
add constraint FK_mytable_parentid FOREIGN KEY ( parentid ) references mytable(id)

ALTER TABLE mytable alter column parentid int null;

insert into mytable(name)
select 'test'

update mytable
set parentid = SCOPE_IDENTITY()
where id = SCOPE_IDENTITY()

ALTER TABLE mytable alter column parentid int not null;

select * from mytable
drop table mytable
0 голосов
/ 23 мая 2011

Не ссылаться на столбец IDENTITY как на внешний ссылающийся внешний ключ.Вместо этого используйте альтернативный ключ таблицы.Я предполагаю, что вы используете IDENTITY в качестве суррогатного ключа, но у каждой таблицы также должен быть естественный ключ, поэтому столбец IDENTITY не должен быть ключом only вашей таблицы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...