powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / В одной таблице два FK на один PK другой таблицы
12 сообщений из 12, страница 1 из 1
В одной таблице два FK на один PK другой таблицы
    #39241763
ru_efim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте.
Есть таблица содержащая два FK на один PK второй таблицы. В общем, если упростить до предела будет так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
CREATE TABLE [A_RUser] ( --Реестр пользователей
	[UserId] [int] NOT NULL ,
	[Family] [varchar] (50) NOT NULL ,
	CONSTRAINT [PK_A_RUser] PRIMARY KEY CLUSTERED ([UserId]) ON [PRIMARY] 
) ON [PRIMARY]
GO

CREATE TABLE [A_Transfer] ( --Акт передачи
	[TransId] [int] IDENTITY (1, 1) NOT NULL ,
	[User_Sender] [int] NOT NULL ,
	[User_Receiver] [int] NOT NULL ,
	[Volume_Transfer] [int] NOT NULL ,
	CONSTRAINT [PK_Trans] PRIMARY KEY CLUSTERED ([TransId]) ON [PRIMARY],
	CONSTRAINT [FK_TransReceiv_RUser]	FOREIGN KEY ([User_Receiver])	REFERENCES [A_RUser] ([UserId]),
	CONSTRAINT [FK_TransSend_RUser]		FOREIGN KEY ([User_Sender])	REFERENCES [A_RUser] ([UserId])
) ON [PRIMARY]
GO
--Наполняем данными
INSERT INTO A_RUser(UserId, Family) VALUES(1, 'Иванов')
INSERT INTO A_RUser(UserId, Family) VALUES(2, 'Петров')
INSERT INTO A_RUser(UserId, Family) VALUES(3, 'Сидоров')
GO
INSERT INTO A_Transfer(User_Sender, User_Receiver, Volume_Transfer) VALUES(1, 2, 10)
INSERT INTO A_Transfer(User_Sender, User_Receiver, Volume_Transfer) VALUES(2, 3, 5)
INSERT INTO A_Transfer(User_Sender, User_Receiver, Volume_Transfer) VALUES(3, 1, 5)


Хоть и упростил до безобразия, но думаю суть понятна.
Вопрос: С одной стороны, все как бы логично, вполне себе нормальное представление реальной ситуации "сегодня петров отправитель, Сидоров получатель, завтра наоборот".
Но с другой стороны какая то ерунда. Каскадное удаление, обновление связанных записей не допустимо (для обоих связей одновременно на MS SQL Server). Запросы с "вытаскиванием через связь", в данном случае Фамилий, ... какие то ... конкретно в этом примере нормально, но ... Если связь будет "длиннее", например через FK через таблицу A_RUser(как "промежуточную") в свою очередь, так же через FK придется "тащить" еще что нибудь из третей таблицы то такая "этажерка" получится.
Короче вопрос, по моему "структура!" какая-то ущербная, то ли таблицы не хватает, то ли Чего? По моему ситуация стандартная, но мой мизерный опыт не позволяет найти решение. Помогите пожалуйста.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39241865
Фотография vmag
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efim,

просто мысли в слух:
- Каскадное удаление, обновление... - если всё по уму, то обычно первичные ключи это счётчики (обновляются не они, а паровоз за ними идущий)
- можно в схеме данных оставить только одну связь (или к отправителю или к получателю) а вторую вытягивать искусственно по мере необходимости в запросах и процедурах
- можно в схеме данных оставить только одну связь (или к отправителю или к получателю), а затем добавить главную таблицу в схему БД ещё один раз (с псевдонимом) и протянуть вторую связь уже от дубликата

ну а так-то нужно пробовать...
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242020
ru_efim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
vmag, спасибо. Но мне КАЖЕТСЯ что в данной схеме именно что-то не так.
Как бы с конкретной реализацией целостности, за счет связей, проблем то и нет. Как вы правильно говорите "обычно первичные ключи это счётчики (обновляются не они, а паровоз за ними идущий)"
Просто на всех этапах с такой схемой возникают какие то проблемы.
Вот на пример, получаем результирующий набор
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
SELECT
	tr.TransId,
	send.Family AS Sender,
	tr.Volume_Transfer AS Volume
	FROM
		A_Transfer AS tr
		INNER JOIN A_RUser AS send ON tr.User_Sender	= send.UserId
		INNER JOIN A_RUser AS recv ON tr.User_Receiver	= recv.UserId


Далее (в общем я вначале упростил до безобразия, а теперь пытаюсь прикрутить к этому что-то реальное)...
Предположим поле A_Transfer.User_Receiver не является обязательным (ну вот передал в некуда и все (предположим, по пустому полю мы определяем например утерю)!) . Я вот, сходу, не могу придумать, как построить запрос, возвращающий такой же набор, как приведенный запрос выше. Хотя всего ДВЕ таблицы.
Вот мне и КАЖЕТСЯ что проблема не в умении строить sql-запросы, а именно в схеме, по этому и написал в данную ветку.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242026
ru_efim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Простите ошибся.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
SELECT
	tr.TransId,
	send.Family AS Sender,
	recv.Family AS Receiver,
	tr.Volume_Transfer AS Volume
	FROM
		A_Transfer AS tr
		INNER JOIN A_RUser AS send ON tr.User_Sender	= send.UserId
		INNER JOIN A_RUser AS recv ON tr.User_Receiver	= recv.UserId
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242040
Кот Матроскин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efim,

Схема нормальная, on delete cascade в рабочих базах не нужен примерно никогда.
Если паче чаяния нужен - можно руками написать удаляющий запрос.
авторПредположим поле A_Transfer.User_Receiver не является обязательным (ну вот передал в некуда и все (предположим, по пустому полю мы определяем например утерю)!). Я вот, сходу, не могу придумать, как построить запрос, возвращающий такой же набор, как приведенный запрос выше.

Заменить в одном месте inner на left, ясное дело.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242070
Cane Cat Fisher
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ситуация с двумя FK на одну таблицу ничего плохого не содержит. Трудности решаемы, если что давайте их обсуждать.

Конкретно по получателю и отправителю - не знаю, что вы отправляете, но обычно отправитель действительно один, а вот получателей как правило бывает несколько.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242104
ru_efim
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СПАСИБО.
Сижу второй день бьюсь с подобной схемой, то тут не так, то здесь не очень. А на запросе "при необязательном поле" совсем расстроился. И началось мне казаться что схема не такая ...
Короче, "Кот Матроскин " спасибо отдельно, ну вот забыл я как то про то что кроме INNER еще и внешние и не только есть.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242109
Mr.Fontaine
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Cane Cat Fisher, ну не знаю про обычно.... Вот например, отправил я посылку с велосипедом, на нескольких получателей. Один в Туле, другой в Магадане, третий вообще в какой-нибудь Нягани. И чё? Куда посылка поедет?
Я конечно согласен, что например спам по электронной почте отправляется обычно нескольким получателям.
Потому всё-таки слово "обычно" кажется мне лишним. "иногда" или "для некоторых типов отправлений" это кончено согласен

P.S. То есть как бы в общем случае требуется отдельная табличка - A_Receivers. Так бы и написали.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242264
mini.weblab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efim,

а "правильно" это как?
задачу вам какую поставили ?
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39242791
Фотография softwarer
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efimНо с другой стороны какая то ерунда. Каскадное удаление, обновление связанных записей не допустимо
Может и не допустимо. А зачем оно нужно? Допустим, Вы одолжили мне сто рублей. Допустим, Вас пристрелили. Я ещё пойму постановку вопроса "в этом случае долг аннулируется, запись о нём нужно удалить", но решительно протестую против "в этом случае нужно каскадно удалить из реальности и меня тоже". Так что ерунда вовсе не в таблицах :)

ru_efimЗапросы с "вытаскиванием через связь", в данном случае Фамилий, ... какие то ... конкретно в этом примере нормально, но ... Если связь будет "длиннее", например через FK через таблицу A_RUser(как "промежуточную") в свою очередь, так же через FK придется "тащить" еще что нибудь из третей таблицы то такая "этажерка" получится.
(пожимая плечами) Два FK не имеют ровным счётом никакого отношения к этой проблеме. Допустим, остался только один FK. Что, "этажерка" станет меньше? Сколько этажей нагромоздил - такую этажерку получишь, закон жизни.

ru_efimКороче вопрос, по моему "структура!" какая-то ущербная, то ли таблицы не хватает, то ли Чего?
Думаете, ещё одна промежуточная таблица сделает этажерку меньше?

Кардинально схем решения этой задачи две: проводки и полупроводки. Об их плюсах и минусах исписаны тысячи страниц, гугль даст миллионы ссылок. Какая из них лучше для Вашей задачи - по "упрощённой для безобразия" не скажешь.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39243599
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efimvmag, спасибо. Но мне КАЖЕТСЯ что в данной схеме именно что-то не так.....
Вот мне и КАЖЕТСЯ что проблема не в умении строить sql-запросы, а именно в схеме, по этому и написал в данную ветку.

когда кажется, надо что делать?
Правильно, надо перекреститься и работать спокойно дальше.
Все у тебя ок со структурой, несколько fk из одной таблицы - нормальное явление.

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

Эту ситуацию необходимо отличать от другой, когда родителей (в смысле связи таблиц) может быть переменное количество. в таком случае нужно делать дополнительную таблицу связи.
...
Рейтинг: 0 / 0
В одной таблице два FK на один PK другой таблицы
    #39243600
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ru_efimПредположим поле A_Transfer.User_Receiver не является обязательным (ну вот передал в некуда и все (предположим, по пустому полю мы определяем например утерю)!) . Я вот, сходу, не могу придумать, как построить запрос, возвращающий такой же набор, как приведенный запрос выше. Хотя всего ДВЕ таблицы.



ты еще и SQL не знаешь...
Вот тебе и кажется все.
Короче, для тебя специально - когда кажется, перекрестись и учи SQL.

А тут надо LEFT JOIN.
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / В одной таблице два FK на один PK другой таблицы
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]