Разница между отношениями один к многим и многим к одному. Один к одному sql


sql - Как создать реальную взаимосвязь "один-к-одному" в SQL Server

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

Я возьму концепцию цыпленка и яйца из принятого ответа, чтобы помочь мне объяснить оговорку.

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

Предостережение состоит в том, что таблица, которая позволяет записи "прийти первым" технически, может иметь запись, созданную без соответствующей записи в другой таблице; однако в этом решении допускается только одна такая запись. Когда создается только одна запись (только цыпленок или яйцо), никакие записи не могут быть добавлены ни к одной из двух таблиц, пока не будет удалена либо "одиночная" запись, либо соответствующая запись будет создана в другой таблице.

Решение:

Добавьте внешние ключи в каждую таблицу, ссылаясь на другую, добавьте уникальные ограничения для каждого внешнего ключа и сделайте один внешний ключ с нулевым значением, а другой - недействительным, а также первичный ключ. Чтобы это сработало, уникальный ограничитель в столбце с нулевым значением должен допускать только один null (это имеет место в SQL Server, не уверен в других базах данных).

CREATE TABLE dbo.Egg ( ID int identity(1,1) not null, Chicken int null, CONSTRAINT [PK_Egg] PRIMARY KEY CLUSTERED ([ID] ASC) ON [PRIMARY] ) ON [PRIMARY] GO CREATE TABLE dbo.Chicken ( Egg int not null, CONSTRAINT [PK_Chicken] PRIMARY KEY CLUSTERED ([Egg] ASC) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE dbo.Egg WITH NOCHECK ADD CONSTRAINT [FK_Egg_Chicken] FOREIGN KEY([Chicken]) REFERENCES [dbo].[Chicken] ([Egg]) GO ALTER TABLE dbo.Chicken WITH NOCHECK ADD CONSTRAINT [FK_Chicken_Egg] FOREIGN KEY([Egg]) REFERENCES [dbo].[Egg] ([ID]) GO ALTER TABLE dbo.Egg WITH NOCHECK ADD CONSTRAINT [UQ_Egg_Chicken] UNIQUE([Chicken]) GO ALTER TABLE dbo.Chicken WITH NOCHECK ADD CONSTRAINT [UQ_Chicken_Egg] UNIQUE([Egg]) GO

Чтобы вставить, сначала необходимо добавить яйцо (с нулевым значением для цыпленка). Теперь можно добавить только курицу, и она должна ссылаться на "невостребованное" яйцо. Наконец, добавленное яйцо можно обновить, и оно должно ссылаться на "невостребованную" курицу. Ни в коем случае нельзя назначать двух цыплят, чтобы ссылаться на одно и то же яйцо или наоборот.

Чтобы удалить, можно следовать той же логике: обновить яйцо Курица до нуля, удалить недавно "невостребованную" курицу, удалить яйцо.

Это решение также позволяет легко переключаться. Интересно, что обмен может быть самым сильным аргументом в пользу использования такого решения, поскольку он имеет потенциальное практическое применение. Обычно в большинстве случаев взаимно-однозначное соотношение двух таблиц лучше реализуется путем простого преобразования двух таблиц в один; однако в потенциальном сценарии две таблицы могут представлять собой по-настоящему разные сущности, которые требуют строгой взаимно-однозначной взаимосвязи, но им необходимо часто менять "партнеров" или перестраиваться в целом, сохраняя при этом одностороннее -отношения после переустановки. Если использовалось более распространенное решение, все столбцы данных одного из объектов должны были быть обновлены/перезаписаны для всех перестраиваемых пар, в отличие от этого решения, где нужно переустановить только один столбец внешних ключей (столбец с нулевым внешним ключом).

Хорошо, это лучшее, что я мог сделать, используя стандартные ограничения (не судите:) Может быть, кто-то найдет это полезным.

qaru.site

sql - MySQL - отношение один к одному?

Теперь я знаю, что есть некоторые ответы об отношениях "один на один", но ни один из них не ответил на мой вопрос, поэтому, пожалуйста, прочитайте это до голосования:)

Я пытаюсь достичь отношения "один к одному" в базе данных MySQL. Например, допустим, что у меня есть таблица "Пользователи" и "Таблица учетных записей". И я хочу быть уверенным, что Пользователь может иметь только одну учетную запись. И что может быть только одна учетная запись для каждого пользователя.

Я нашел два решения для этого, но не знаю, что использовать, и есть ли другие варианты.

Первое решение:

DROP DATABASE IF EXISTS test; CREATE DATABASE test CHARSET = utf8 COLLATE = utf8_general_ci; USE test; CREATE TABLE users( id INT NOT NULL AUTO_INCREMENT, user_name VARCHAR(45) NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; CREATE TABLE accounts( id INT NOT NULL AUTO_INCREMENT, account_name VARCHAR(45) NOT NULL, user_id INT UNIQUE, PRIMARY KEY(id), FOREIGN KEY(user_id) REFERENCES users(id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;

В этом примере я определяю внешний ключ в аккаунтах, указывающих на первичный ключ у пользователей. И тогда я делаю внешний ключ UNIQUE, поэтому в аккаунтах могут быть два одинаковых пользователя. Чтобы присоединиться к таблицам, я бы использовал этот запрос:

SELECT * FROM users JOIN accounts ON users.id = accounts.user_id;

Второе решение:

DROP DATABASE IF EXISTS test; CREATE DATABASE test CHARSET = utf8 COLLATE = utf8_general_ci; USE test; CREATE TABLE users( id INT NOT NULL AUTO_INCREMENT, user_name VARCHAR(45) NOT NULL, PRIMARY KEY(id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8; CREATE TABLE accounts( id INT NOT NULL AUTO_INCREMENT, account_name VARCHAR(45) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(id) REFERENCES users(id) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;

В этом примере я создаю внешний ключ, который указывает от первичного ключа на первичный ключ в другой таблице. Поскольку первичные ключи по умолчанию UNIQUE, это делает это отношение "один к одному". Чтобы присоединиться к таблицам, я могу использовать это:

SELECT * FROM users JOIN accounts ON users.id = accounts.id;

Теперь вопросы:

  • Каков наилучший способ создания отношений One to One в MySQL?
  • Есть ли другие решения, кроме этих двух?

Я использую MySQL Workbench, и когда я создаю отношения One To One на диаграмме EER и позволяю MySQL Workbench создавать SQL-код, я могу получить отношение "Один к многим": S Что меня смущает: S

И если я импортирую какое-либо из этих решений в диаграмму EER MySQL Workbench, он распознает отношения как от одного до многих: S Thats также запутывает.

Итак, что было бы лучшим способом определить отношения Один к одному в MySQL DDL. И какие варианты есть для этого?

Спасибо!!

qaru.site

Разница между отношениями один к многим и многим к одному Безопасный SQL

Да, это наоборот. Это зависит от того, на какой стороне отношения присутствует сущность.

Например, если один отдел может работать для нескольких сотрудников, тогда отдел для сотрудников является одним из многих (в одном отделении работают многие сотрудники), а отношение сотрудников к отделу – это много к одному (многие сотрудники работают в одном отделе).

Дополнительная информация о типах отношений: отношения базы данных – документация IBM DB2

с http://www.sum-it.nl/cursus/dbdesign/english/intro030.php3

Большинство отношений между таблицами – один-ко-многим.

Пример:

* One area can be the habitat of many readers. * One reader can have many subscriptions. * One newspaper can have many subscriptions.

Отношение «много к одному» такое же, как «один ко многим», но с другой точки зрения.

* Many readers live in one area. * Many subscriptions can be of one and the same reader. * Many subscriptions are for one and the same newspaper.

Какова реальная разница между отношениями один к многим и многим?

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

В отношении « один ко многим» локальная таблица имеет одну строку, которая может быть связана со многими строками в другой таблице. В примере из SQL для новичков один Customer может быть связан со многими Order s.

В противоположных отношениях « много-к-одному» локальная таблица может иметь много строк, которые связаны с одной строкой в ​​другой таблице. В нашем примере многие Order s могут быть связаны с одним Customer . Эта концептуальная разница важна для умственного представления.

Кроме того, схема, которая поддерживает взаимосвязь, представлена ​​по-разному в таблицах Customer и Order . Если у клиента есть id столбцов и name :

id,name 1,Bill Smith 2,Jim Kenshaw

Затем для того, чтобы Customer был связан с Order s, многие реализации SQL добавляют в таблицу Order столбец, в котором хранится id связанного Customer (в этой схеме customer_id :

id,date,amount,customer_id 10,20160620,12.34,1 11,20160620,7.58,1 12,20160621,158.01,2

В приведенных выше строках данных, если мы посмотрим на столбец идентификатора customer_id , мы видим, что Bill Smith (клиент-идентификатор № 1) имеет 2 заказа, связанных с ним: один за 12,34 доллара США и один за 7,58 доллара США. Jim Kenshaw (идентификатор клиента № 2) имеет только 1 заказ за $ 158,01.

Важно понимать, что обычно отношения «один ко многим» фактически не добавляют никаких столбцов в таблицу, которая является «одной». У Customer нет дополнительных столбцов, которые описывают связь с Приложением. На самом деле у Customer также могут быть отношения «один ко многим» с таблицами ShippingAddress и SalesCall но при этом не добавляются дополнительные столбцы в таблицу Customer .

Тем не менее, для описания отношения «один-к-одному» часто используется столбец с id во множестве таблиц, который является внешним ключом к одной таблице, и в этом случае в Order добавляется столбец customer_id . К связанному заказу № 10 за $ 12,34 Bill Smith мы присваиваем столбец customer_id идентификатору Bill Smith 1.

Надеюсь это поможет.

Ответ на ваш первый вопрос: оба схожи,

Ответ на ваш второй вопрос: «один-ко-многим» – MAN (таблица MAN) может иметь более одной жены (таблица WOMEN) много-к-одному -> более одной женщины вышли замуж за одного мужчины.

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

sql.fliplinux.com

Отношения один к одному с несколькими таблицами Безопасный SQL

Сказать,

У меня 3 таблицы.

User который содержит основную информацию о пользователях.

SectionA который содержит больше информации о пользователе.

SectionB который также содержит больше информации о пользователе.

Для каждого пользователя могут быть только данные SectionA и SectionB .

Моя идея состояла в том, чтобы создать такой дизайн таблицы:

id name section_a_id section_b_id 1 matt 1 1

Проблема заключается в том, что section_a_id и section_b_id не могут автоматически увеличиваться, поскольку они не являются первичными.

Поэтому я попробовал другой подход и решил, что первичный ключ id в User должен быть внешним ключом, который ссылается на section_a_id и section_b_id`. Но я не могу этого сделать, так как mysql позволяет ссылаться только на одну таблицу.

Итак, как мне подойти к этой ситуации?

Solutions Collecting From Web of "Отношения один к одному с несколькими таблицами"

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

Некоторые положительные моменты, которые я вижу для этого подхода:

  • Легче вставлять, обновлять и удалять операции.
  • Более быстрый поиск данных при меньшем количестве подключений.
  • Меньшее количество индексов, потому что вы индексируете первичный ключ для одной таблицы вместо трех таблиц.

Кажется, у вас есть:

  • Отношение 1-n User-SectionA
  • Отношение 1-n User-SectionB

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

Для каждого пользователя могут быть только данные SectionA и SectionB.

Это вызывает вопрос о том, почему вы храните данные в разных таблицах. Иногда это замечательно – разные пользователи могут быть в разных таблицах.

Одним из решений является наличие первичного ключа SectionA и SectionB качестве внешней ссылки на UserId . Да, это разрешено.

Другим решением является наличие sectionA_id и sectionA_id в таблице users . Затем вы можете иметь автоматически увеличивающийся идентификатор в каждой из ссылочных таблиц.

Редкое использование для 1: 1

  • У вас действительно слишком много столбцов;
  • Таблица огромна, и вы не хотите, чтобы ALTER стол добавлял больше;
  • Одна из таблиц в основном необязательна, и вы используете LEFT JOIN для получения нулей.

Причинение неправильных установок AUTO_INCREMENT

  • Столбец не должен быть PRIMARY KEY , даже UNIQUE ; он должен быть только первым столбцом в каком-то индексе.
  • Вам не обязательно иметь столбец AUTO_INCREMENT . Часто лучше использовать «естественный» ПК – некоторый столбец (или комбинацию столбцов), который по своей сути является UNIQUE .

При создании пары таблиц 1: 1 это один из способов сделать это

  1. Создайте первую таблицу с PRIMARY KEY которая является AUTO_INCREMENT .
  2. Создайте вторую таблицу с PRIMARY KEY которая идентична другой, но не AUTO_INCREMENT .
  3. При вставке строки используйте LAST_INSERT_ID() для получения идентификатора.
  4. Используйте это значение для явного указания идентификатора для второй таблицы.

sql.fliplinux.com

sql - Разница между отношениями один к многим и многим к одному

Какова реальная разница между отношениями от одного до многих и от одного до одного?

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

В отношении one-to-many локальная таблица имеет одну строку, которая может быть связана со многими строками в другой таблице. В примере из SQL для начинающих один Customer может быть связан со многими Order s.

В противоположном соотношении много-к-одному локальная таблица может иметь много строк, которые связаны с одной строкой в ​​другой таблице. В нашем примере многие Order могут быть связаны с одним Customer. Эта концептуальная разница важна для умственного представления.

Кроме того, схема, которая поддерживает взаимосвязь, представлена ​​по-разному в таблицах Customer и Order. Если у клиента есть столбцы id и name:

id,name 1,Bill Smith 2,Jim Kenshaw

Затем для Customer, связанного с Order s, многие реализации SQL добавляют в таблицу Order столбец, в котором хранится id связанного Customer (в этой схеме customer_id:

id,date,amount,customer_id 10,20160620,12.34,1 11,20160620,7.58,1 12,20160621,158.01,2

В приведенных выше строках данных, если мы смотрим на столбец customer_id id, мы видим, что Bill Smith (customer-id # 1) имеет 2 заказа, связанных с ним: один для $12,34 и один за $7,58. Jim Kenshaw (идентификатор клиента № 2) имеет только 1 заказ за $158,01.

Важно понимать, что обычно отношения "один ко многим" фактически не добавляют никаких столбцов в таблицу, которая является "одной". Customer не имеет дополнительных столбцов, которые описывают связь с Order. На самом деле Customer может также иметь отношение "один ко многим" с таблицами ShippingAddress и SalesCall и, тем не менее, не содержать дополнительных столбцов, добавленных в таблицу Customer.

Однако для описания отношения "один-к-одному" часто используется столбец id, который добавляется во многие таблицы, которые являются внешними ключами для одной таблицы. В этом случае столбец customer_id добавлен в Order. Для связанного порядка # 10 за $12.34 до Bill Smith мы назначаем столбец customer_id Bill Smith id 1.

Надеюсь, что это поможет.

qaru.site

sql - Определение отношения "один-к-одному" SQL

Хорошо, этот ответ специфичен для SQL Server, но должен быть адаптирован к другим РСУБД с небольшой работой. Насколько я вижу, мы имеем следующие ограничения:

  • Счет-фактура может быть связан с 0 или 1 рабочими заказами
  • Рабочий заказ должен быть связан с факсом или ABC или DEF

Я бы создал таблицу WorkOrder следующим образом:

CREATE TABLE WorkOrder ( WorkOrderID int IDENTITY(1,1) not null, /* Other Columns */ InvoiceID int null, ABCID int null, DEFID int null, /* Etc for other possible links */ constraint PK_WorkOrder PRIMARY KEY (WorkOrderID), constraint FK_WorkOrder_Invoices FOREIGN KEY (InvoiceID) references Invoice (InvoiceID), constraint FK_WorkOrder_ABC FOREIGN KEY (ABCID) references ABC (ABCID), /* Etc for other FKs */ constraint CK_WorkOrders_SingleFK CHECK ( CASE WHEN InvoiceID is null THEN 0 ELSE 1 END + CASE WHEN ABCID is null THEN 0 ELSE 1 END + CASE WHEN DEFID is null THEN 0 ELSE 1 END /* + other FK columns */ = 1 ) )

Таким образом, в основном эта таблица ограничивается только FK одной другой таблицей, независимо от того, сколько PK определено. Если необходимо, вычисленный столбец может сообщить вам "Тип" элемента, с которым он связан, на основе которого столбец FK не является нулевым, или тип и один столбец int могут быть реальными столбцами, а также InvoiceID, ABCID и т.д. могут быть вычислены столбцы.

Последнее, что нужно сделать, состоит в том, что в счете есть только 0 или 1 Work Orders. Если ваш RDMBS игнорирует нули в уникальных ограничениях, это так же просто, как применение такого ограничения для каждого столбца FK. Для SQL Server вам необходимо использовать отфильтрованный индекс ( >= 2008) или индексный вид (< = 2005). Я просто покажу отфильтрованный индекс:

CREATE UNIQUE INDEX IX_WorkItems_UniqueInvoices on WorkItem (InvoiceID) where (InvoiceID is not null)

Другим способом решения проблемы с WorkOrders является включение столбца типа WorkOrder в WorkOrder (например, "Invoice", "ABC", "DEF" ), включая вычисляемый или столбец, ограниченный контрольным ограничением, чтобы содержать значение соответствия в таблицу ссылок и ввести второй внешний ключ:

CREATE TABLE WorkOrder ( WorkOrderID int IDENTITY(1,1) not null, Type varchar(10) not null, constraint PK_WorkOrder PRIMARY KEY (WorkOrderID), constraint UQ_WorkOrder_TypeCheck UNIQUE (WorkOrderID,Type), constraint CK_WorkOrder_Types CHECK (Type in ('INVOICE','ABC','DEF')) ) CREATE TABLE Invoice_WorkOrder ( InvoiceID int not null, WorkOrderID int not null, Type varchar(10) not null default 'INVOICE', constraint PK_Invoice_WorkOrder PRIMARY KEY (InvoiceID), constraint UQ_Invoice_WorkOrder_OrderIDs UNIQUE (WorkOrderID), constraint FK_Invoice_WorkOrder_Invoice FOREIGN KEY (InvoiceID) references Invoice (InvoiceID), constraint FK_Invoice_WorkOrder_WorkOrder FOREIGN KEY (WorkOrderID) references WorkOrder (WorkOrderID), constraint FK_Invoice_WorkOrder_TypeCheck FOREIGN KEY (WorkOrderID,Type) references WorkOrder (WorkOrderID,Type), constraint CK_Invoice_WorkOrder_Type CHECK (Type = 'INVOICE') )

Единственный недостаток этой модели, хотя и ближе к вашему первоначальному предложению, заключается в том, что у вас может быть заказ на работу, который фактически не связан с каким-либо другим элементом (хотя он, как утверждается, относится к, например, INVOICE).

qaru.site

Связи в моделях. Один к одному: Быстро и кратко, полно и точно

Если у читателей был опыт разработки с использованием БД, то вероятно вам уже известно, как создавать SQL запросы на выборку из разных таблиц. В Ruby on Rails все выглядит немного более привлекательно. Так как Active Record является полноценной ORM, то вполне понятно, что работа со связанными таблицами может быть гораздо удобнее.

Как уже вы знаете, каждой таблице в БД, в ROR(ActiveRecord) сопоставляет одноименный обьект (модель), правда стоит учитывать, что имя таблицы должно быть во множественном числе, в отличии от имени обьекта(модели). Также для доступа к каждому полю таблицы существует одноименный метод в модели (Например таблица users содержит поле name, то в модели оно доступно, как obj.name, где obj - объект класса User). Потому и говорят что таблица "мапится" моделью - что и есть основным принципом ORM. Детальнее тут.

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

Так как вместо таблиц мы используем модели, то нам хотелось бы написать что-то типа такого:user.address.street - где User и Adress єкземпляры классов соответствующих моделей, а street - свойство экземпляра класса адреса. Заманчиво, не правда ли?

Для того, чтобы написать подобное, использем SQL:

SELECT addresses.nameFROM addresses INNER JOIN users on users.id = addresses.user_idнам бы пришлось выполнить запрос и достать из него нужное поле... Как по мне, то немного неудобно.

Так как же, все-таки, изменить модели, чтобы мы могли так ими оперировать?Именно это и является темой данной статьи. Давайте рассмотрим запрос на SQL более детально, так как нам надо выяснить для себе некоторые моменты.

Для того, чтобы связать две таблицы как "1 к 1", нам необходимо выяснить для себя - какая таблица является родительской, а какая подчиненной.

Оказывается, это довольно-таки просто: рассмотрим 2 строку запроса, а именно условие обьеденения

users.id = address.user_idТаблица Addresses содержит первичный ключ таблицы Users, что автоматически делает ее подчиненной.

Сформулируем словами связи между таблицами: таблица Users содержит таблицу Addresses с одной стороны, таблица Addresses относится к таблице Users - с другой стороны. Все вполне логично. Теперь посмотрим, как все выше сказанное реализовать в моделях RoR:class Address < ActiveRecord::Base   belongs_to :user   # дальше идет код который описывает управление данными моделиendclass User < ActiveRecord::Base   has_one :address   # дальше идет код который описывает управление данными моделиendВ самом начале описания модели, мы указываем как она связана с другими моделями. Для реализации связи "1 к 1", достаточно "сказать" модели User - что она has_one (содержит один) Address, а Address в свою очередь belongs_to(содержит) User. Вот и все!

Что мы получили в результатеС этого момента модели являются связанными между собой, и при построении запросов типа: user.address.street ActiveRecord автоматически будет добавлять связи.Теперь возможно, используя связи, пользоваться подчиненной моделью (таблицей) как частью таблицы родителя(свойством модели родителя), ну думая о том, что на самом деле данные разнесены по разным таблицам.Имеем полное право вычитать адресные данные пользователя:User.address.find(:all)

street = User.find_by_id(id).address.street

interestabout.blogspot.com