Слияние SQL связанных записей - PullRequest
2 голосов
/ 20 сентября 2011

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

Чтобы сделать его более конкретным, скажем, две записи в этой центральной таблице: Initech и Contoso . Initech и Contoso связаны со многими другими записями в связанных таблицах, таких как Сотрудники , AccountingTransactions и т. Д. Предположим, что эти два слились (Initech купил Contoso) и с точки зрения данных, это действительно это так же просто, как объединение всех записей. Какой самый простой способ взять все связанные с Contoso записи, заставить их указать Initech, а затем удалить Contoso?

ОБНОВЛЕНИЕ с CASCADE очень заманчиво приближается, но, очевидно, оно не может работать без отключения ограничений и последующего их включения (гадость).

Есть ли хороший общий способ сделать это, не выискивая каждую отдельную связанную таблицу и не перенося их одну за другой? Это должно быть общим требованием. В этом проекте он встречается в двух местах и ​​его можно суммировать следующим образом: сущность А должна контролировать все текущие элементы управления сущности В. Как я могу это сделать?

До слияния:

Companies
ID Name
1  Contoso
2  Initech

Employees
ID Name CompanyId
1  Bob  1 
2  Ted  2

После слияния:

Companies
ID Name
2  Initech

Employees
ID Name CompanyId
1  Bob  2 
2  Ted  2

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

Ответы [ 3 ]

1 голос
/ 30 сентября 2011

Этот запрос, вероятно, зависит от поставщика, но в MySQL:

UPDATE Employees e, Cars c, OtherEntity o
  SET e.CompanyId = 2, c.CompanyId = 2, o.CompanyID = 2
  WHERE e.CompanyID = 1 OR c.CompanyId = 1 OR o.CompanyId = 1;
0 голосов
/ 20 сентября 2011

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

Одним из обходных путей может быть внедрение шаблона родительского контроля в вашей центральной таблице (или абстрагирование его в другую таблицу). Затем вы получите что-то вроде

Companies 
ID ParentID Name 
1  2        Contoso 
2  null     Initech  

или

Companies 
ID ParentID Name 
1  3        Contoso 
2  3        Initech  
3  null     MegaInitech

и все ваши запросы, которые присоединяются к этой центральной Companies таблице, теперь проверяют ID и ParentID;

SELECT * 
FROM Employees          
WHERE CompanyId IN (SELECT ID FROM Companies WHERE ID = @id OR ParentID = @ID)

Абстрагируйте это от представления или функции

CREATE FUNCTION fn_IsMemberOf
(
    @companyId INT,
    @parentId INT
)
RETURNS BIT
AS
BEGIN   
    DECLARE @result BIT = 0
    SELECT @result = 1 FROM Companies 
    WHERE ID = @companyId
        AND COALESCE(ParentID, ID) = @parentID
    RETURN @result
END

SELECT * 
FROM Employees          
WHERE fn_IsMemberOf(CompanyId, 1) = 1

(не проверял это, но вы поняли)

0 голосов
/ 20 сентября 2011

Кратко, нет;универсального способа сделать это не существует.

Рассмотрим пример базы данных с таблицами Companies, Employees, Departments и AccountingTransactions.

Вам необходимо удалить одну из записей компании (потому что послепри слиянии вы будете записывать только текущее состояние дел).

Вам необходимо изменить записи сотрудников, чтобы изменить компанию-работодателя.Однако вполне возможно, что в обеих компаниях есть номер сотрудника N, и одной из них (предположительно компании Contoso) придется назначить новый номер сотрудника.

Возможно, вы столкнулись с проблемой, что отдел 1 вДанные Conotoso - это инженерные, а в Initech - финансовые.Таким образом, вам нужно беспокоиться о том, как вы собираетесь сопоставлять номера отделов между двумя компаниями, и тогда вы столкнетесь с проблемой назначения сотрудников Contoso в отделы Initech.сохранить исторические учетные записи Contoso на имя Contoso, в то время как некоторые (самые последние) транзакции необходимо будет перенести на имя Initech.Так что, возможно, вы, в конце концов, не будете удалять запись Contoso из таблицы компаний, но вы не сможете использовать ее для идентификации каких-либо новых записей.

Это лишь небольшая выборка причинпочему такие отображения не могут быть легко автоматизированы.

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