#sql #row #field
#sql #строка #поле
Вопрос:
Может кто-нибудь подсказать мне, как создать эту структуру базы данных. Вот пример:
Table "countries":
id, countryname
1, "US"
2, "DE"
3, "FR"
4, "IT"
Теперь у меня есть другая таблица «продукты», и в ней я хотел бы сохранить все страны, где доступен этот продукт:
Table "products":
id,productname,countries
1,"product1",(1,2,4) // available in countries US, DE, IT.
2,"product2",(2,3,4) // available in countries DE, FR, IT.
Мой вопрос:
Как мне спроектировать структуру таблицы в «продуктах», чтобы иметь возможность хранить несколько стран?
Моя лучшая идея — поместить туда строку, разделенную запятыми (т. Е. «1,2,4»), затем разделить эту строку для поиска каждой записи. Но я сомневаюсь, что это лучший способ сделать это?
РЕДАКТИРОВАТЬ: Спасибо всем за вашу помощь, потрясающе! Было трудно выбрать правильный ответ, в конце концов я выбрал Gregs, потому что он указал мне на объяснение соединения и привел пример, как его использовать.
Ответ №1:
Вам нужна таблица пересечений для этого отношения многие ко многим.
Table Country
CountryID, CountryName
Table CountryProduct
CountryID, ProductID
Table Product
ProductID, ProductName
Затем вы внутренне объединяете все 3 таблицы, чтобы получить свой список стран и продуктов.
Select * From Country
Inner Join CountryProduct On Country.CountryID = CountryProduct.CountryID
Inner Join Product On CountryProduct.ProductID = Product.ProductID
Ответ №2:
Без денормализации вам нужно будет добавить дополнительную таблицу
Table Product countries
ProductID CountryID
1 1
1 2
1 4...
Ответ №3:
То, о чем вы говорите, — это нормализация. У вас структура «многие ко многим», поэтому вам следует создать другую таблицу, чтобы связать их. Вы никогда не должны (хорошо, практически никогда) использовать строки с разделителями для хранения списка значений в реляционной базе данных.
Вот пример настройки:
product_countries table
productid | countryid
---------- -----------
1 | 1
1 | 2
1 | 4
2 | 2
2 | 3
2 | 4
Вы можете использовать внешний ключ для каждой другой таблицы, а затем преобразовать их обе в составной первичный ключ.
Затем вы можете получить список поддерживаемых продуктов для идентификатора страны следующим образом:
SELECT * FROM products, product_countries
WHERE products.id = product_countries.productid
AND product_countries.countryid = $cid
Комментарии:
1. почему бы не использовать объединение? для меня это всегда выглядит немного странно
2. Логика при использовании
JOIN
была бы более запутанной для новичка в SQL, которым, очевидно, является OP. Конечно,JOIN
тоже сработало бы, но без него логика яснее и ее легче понять.3. Спасибо вам и всем остальным за помощь!! Да, SQL-новичок здесь. Один подвопрос: этот SQL-оператор кажется мне медленным — предположим, у меня более 100000 продуктов, не займет ли это много времени для перебора product_countries?
4. Не должно выполняться. Поскольку оба столбца являются как первичными, так и внешними ключами, они будут проиндексированы.
Ответ №4:
Вы также могли бы создать третью таблицу countries_products с полями country_id и product_id.
Ответ №5:
наилучший подход для реляционных баз данных заключается в следующем :
Одна таблица для стран, скажем, country_id, country_desc (country_id является основным)
одна таблица для продуктов, скажем, product_id, product_desc и столько столбцов, сколько вы хотите (product_id является основным)
если бы у вас наверняка была только одна страна, было бы достаточно иметь внешний ключ, указывающий на country_id в каждой строке product. Наличие внешнего ключа утверждает, что существует фактическая страна, имеющая идентификатор country_id, ссылающийся на таблицу country.
В вашем случае у вас есть несколько стран для продукта, поэтому добавьте отдельную ассоциативную таблицу product_id, country_id
оба ключа первичные, а также оба внешних.