#sql #sql-server #tsql #parent-child #sql-insert
#sql #sql-сервер #tsql #родитель-потомок #sql-вставка
Вопрос:
В настройке SQL Server 2008 R2 у меня есть table1 (id, col1-1, col1-2, ...)
и table2 (id, table1_id, col2-1, col2-2, ...)
, где table2.table1_id
указывает на table1.id
(т. Е. Отношение внешнего ключа к первичному ключу).
Как мне обеспечить соблюдение правила, согласно которому каждый раз, когда кто-то вставляет запись table1
, он также должен создавать запись table2
?
Я бы предположил, что очевидным механизмом для использования здесь являются триггеры, но это может привести к проблеме с курицей и яйцом, поскольку триггеру потребуется запись table2
in для создания записи in table1
, но для создания записи in table2
сначала мне нужно table1.id
, чтобы значение уже существовало. Как это преодолеть?
Мне нужно, чтобы принудительное выполнение было автоматическим и встроенным в базу данных. Часто выполняемое задание для проверки наличия записей table1
без соответствующих записей table2
не приведет к сокращению, и правило должно применяться в режиме реального времени, когда кто-то фактически создает запись table1
.
Комментарии:
1. Хотя это и не «автоматическая и встроенная», если вы предоставляете хранимую процедуру для реализации
AddMultitableStuff
, предоставляете ей доступ на запись к таблицам и запрещаете пользователям доступ на запись к таблицам, вы можете управлять добавлением строк с помощью произвольных бизнес-правил.
Ответ №1:
Для этого можно просто использовать предложение OUTPUT . Вот простой пример
CREATE TABLE Parent(Id INT, Col VARCHAR(45));
CREATE TABLE Child(Id INT, Col VARCHAR(45));
INSERT INTO Parent(Id, Col)
OUTPUT INSERTED.Id, INSERTED.Col INTO Child
VALUES(1, 'SomeValue');
SELECT *
FROM Parent P
JOIN Child C ON P.Id = C.Id;
Обратите внимание, что расширенная поддержка SQL Server 2008/2008 R2 заканчивается 9 июля 2019 года. Вам следует выполнить обновление как можно скорее.
Ответ №2:
Проблему с курицей и яйцом можно предотвратить, но я тестировал на Windows SQL 2016:
CREATE TRIGGER [dbo].[Table1_Insert]
ON [dbo].[Table1RR] AFTER INSERT
AS
IF rowcount_big() = 0 RETURN --leave trigger if no record (-s) inserted in the Table1
SET NOCOUNT ON
ALTER TABLE dbo.Table2RR NOCHECK CONSTRAINT FK_Table2_Table1 -- resolve chicken and the egg problem
INSERT INTO dbo.Table2RR select id,null,null from inserted order by id
ALTER TABLE dbo.Table2RR CHECK CONSTRAINT FK_Table2_Table1
GO
ALTER TABLE [dbo].[Table1RR] ENABLE TRIGGER [Table1_Insert]
GO