2013-09-06 2 views
0

Есть уже сообщения, например this one, в которых говорится, что «наивное» наследование в SQL, а именно использование одной таблицы на уровне класса, - это обычная вещь. Примерsql: вставить объект на несколько таблиц

create table parent 
(id integer primary key 
, more-parent-attributes 
); 

create table child 
(id integer primary key references parent(id) on delete cascade 
, more-child-attributes 
); 

Мой вопрос заключается только в том, как вставитьchild в идиоматическом образе ANSI SQL в таблицу. Ограничение внешнего ключа делает требование о том, чтобы мы сначала ввели новую строку в parent, а затем новую строку в child, используя идентификатор строки parent. Я не знаю, как это сделать (получите этот идентификатор) безопасно и portably и используя только один запрос. Подсказка: я скорее начинающий и не знаю императивного программирования SQL - просто в случае существует очевидное императивное решение.

+0

Возможно, вам понадобится более одного оператора SQL, завернутого в одну транзакцию. – Stewart

+0

2 Вставить в ту же транзакцию (1 для родителя, 1 для ребенка) –

+0

Как получить идентификатор вставленной строки 'parent' надежно? Не могли бы вы предоставить конкретный код? Извините, если это глупый вопрос. –

ответ

0

Вы должны выполнить две вставки.

Первая вставка добавить строку в родительской таблице, вторая вставить добавить строку в дочерней таблице.

Две операции вставки могут быть сгруппированы в одну и ту же транзакцию.

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

Показать ниже:

Шаг 1:

INSERT INTO parent (id, more att) values (your ID, other values) 

Обратите внимание о ID значение, вы можете использовать NEWID() (сервер Sql) UUID() (MySql) или autoincremental целое поле

Шаг 2:

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

SELECT id FROM parent where functional_key satisfacted 

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

Таким образом, ваш запрос становится:

SELECT id FROM parent WHERE register_no = 'YOUR_REGISTER_NUMBER' 

Шаг 3:

INSERT INTO child (id, fk_parent, other fields) values(id, fk_parent, other fields) 

fk_parent поле должно быть оценено с результатом Шаг 2.

На этом этапе вы можете:

Значение fk_parent с переменной или вы можете использовать подзапрос (шаг 2) в вашей вставке s tatement.

+0

Не могли бы вы предоставить конкретный код? Это безопасный способ получить именно идентификатор вставленной строки 'parent'? –

+0

Если бы я получил вас правильно (?), То это то же самое, что предлагал @Romoku (и имеет те же ограничения). –

+0

@Jo So: Да, то же самое. –

0

scope_identity() является то, что вы ищете:

DECLARE @Id INT 

INSERT INTO parent (more-parent-attributes) values (.....) 
SET @Id = Scope_Identity() 

INSERT INTO child (parent(id), more-child-attributes) SELECT @Id, ....more-child-attributes 

scope_identity() возвращает столбец идентификаторов в той же области.Это означает, что ключ Родитель должен быть столбец Идентичность:

id int IDENTITY(1,1)PRIMARY KEY 

, и я думаю, что это так, как если бы вы решали, что является ключом идентификатор Родитель, вы бы использовать то же самое для ребенка вставки.

+0

Как вы знаете, в новых версиях SQL Server предложение вывода является лучшим выбором, чем scope_identity. У Scope_identity есть ошибка, связанная с параболизмом, которую они не намерены исправлять (потому что они хотят, чтобы вы использовали функцию OUTPUT, которую я подозревал). – HLGEM

+0

Спасибо @HLGEM, это хорошо знать. Я этого не знал. Я работал над базой данных со многими триггерами, использующими Scope_Identity(), и у меня никогда не было проблем, но после некоторых поисковых запросов я вижу, что OUTPUT - лучший вариант, как вы предложили. – user007

+0

scope_identity был методом prferred до выхода OUTPUT, вероятно, когда большинство из этих вещей было написано. Он отлично работает, если вы не используете параллелизм. Но новая разработка должна использовать OUTPUT – HLGEM

0

В итоге я сделал что-то подобное. Для получения Id вам необходимо указать часть данных, которую вы можете вставить в Parent. Если вы используете это в каком-то приложении, вы можете использовать GUID. В моем приложении я использовал конкатенацию исходных столбцов, которые, как я знал, создавали бы уникальное значение.

CREATE TABLE Parent 
(
    Id INT IDENTITY NOT NULL PRIMARY KEY 
    ,SourceId VARCHAR(50) NOT NULL 
); 

CREATE TABLE Child 
(
    ParentId INT NOT NULL REFERENCES Parent (Id) 
    ,Data VARCHAR(20) 
); 

-- Some procedure inserts the unique value 
INSERT INTO Parent (SourceId) VALUES ('UNIQUE VALUE'); 

-- Another procedure inserts data using the unique value 
DECLARE @Id INT; 

SELECT @Id = Id FROM Parent WHERE SourceId = 'UNIQUE VALUE'; 

INSERT INTO Child (ParentId, Data) VALUES (@Id, 'Some Data'); 
+0

У меня тоже была эта идея, но мне это не особенно нравится, потому что: Это взломать. Невозможно создать уникальную ценность. Он ест пространство не по какой-либо другой причине, кроме как сделать взлом возможным. –

+0

Я видел этот образец, использованный несколько раз раньше. Это может показаться неподдельным, но в большинстве случаев оно выполняется, особенно если приложение не имеет статуса. – Romoku

Смежные вопросы