如何实现多对多数据库关系?

时间:2018-04-04 05:23:04

标签: database sqlite many-to-many

我正在构建一个SQLite数据库,我不知道如何继续这种情况。

我将使用一个真实的例子来解释我需要的东西:

我有一个列表产品,由各州的许多商店出售。并非每个Store都会销售特定的Product,而那些只会State出售的Product或其他Store。大多数商店在大多数州销售 a 产品,但并非全部。

例如,我们说我想在夏威夷买一台真空吸尘器。 Joe的硬件在18个州销售真空吸尘器,但夏威夷却没有。 沃尔玛在夏威夷销售吸尘器,但不销售微波炉。 汉堡王根本不销售吸尘器,但会在美国的任何地方给我一个Whopper。

因此,如果我在夏威夷并寻找真空,我应该只得到 Walmart 。虽然其他商店可能会销售真空吸尘器,并且可能会在夏威夷销售,但他们并不做这两件事,但沃尔玛确实如此。

如何在关系数据库中有效地创建这种类型的关系(具体来说,我目前正在使用SQLite,但将来需要能够转换为MySQL)。

显然,我需要StateProductStore的表格,但我对如何创建和查询表示不知所措加入表......

例如,如果我查询某个State,我将如何确定哪个JBoss EAP会在特定的10:13:54,991 INFO [org.jboss.as.remoting] (MSC service thread 1-4) JBAS017100: Listening on 127.0.0.1:4447 10:13:55,179 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/camel-core-2.19.3.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,179 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/caffeine-2.4.0.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,179 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/slf4j-api-1.7.22.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,179 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/jasypt-1.9.2.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,195 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/jaxb-core-2.2.11.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,195 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry optional/jaxb-impl-2.2.11.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/camel-jasypt-2.19.3.jar does not point to a valid jar for a Class-Path reference. 10:13:55,210 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry jaxb-api.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/jaxb-core-2.2.11.jar does not point to a valid jar for a Class-Path reference. 10:13:55,226 WARN [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015960: Class Path entry jaxb-core.jar in /C:/Users/IBM_ADMIN/EAP-6.4.0/standalone/deployments/restapi-sample-1.0.0.war/WEB-INF/lib/jaxb-impl-2.2.11.jar does not point to a valid jar for a Class-Path reference. 10:13:55,257 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-1) JBWEB003001: Coyote HTTP/1.1 initializing on : http-127.0.0.1:8080 10:13:55,319 INFO [org.apache.coyote.http11.Http11Protocol] (MSC service thread 1-1) JBWEB003000: Coyote HTTP/1.1 starting on: http-127.0.0.1:8080 10:13:56,443 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-2) JBAS010400: Bound data source [java:jboss/datasources/ExampleDS] 10:13:56,835 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-7) MSC000001: Failed to start service jboss.module.service."deployment.restapi-sample-1.0.0.war".main: org.jboss.msc.service.StartException in service jboss.module.service."deployment.restapi-sample-1.0.0.war".main: JBAS018759: Failed to load module: deployment.restapi-sample-1.0.0.war:main at org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:94) [jboss-as-server-7.5.19.Final-redhat-2.jar:7.5.19.Final-redhat-2] at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:2064) [jboss-msc-1.1.7.SP1-redhat-1.jar:1.1.7.SP1-redhat-1] at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1987) [jboss-msc-1.1.7.SP1-redhat-1.jar:1.1.7.SP1-redhat-1] at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [rt.jar:1.8.0_144] at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [rt.jar:1.8.0_144] at java.lang.Thread.run(Unknown Source) [rt.jar:1.8.0_144] Caused by: org.jboss.modules.ModuleNotFoundException: com.fasterxml.jackson.core.jackson-databind:main at org.jboss.modules.Module.addPaths(Module.java:1055) [jboss-modules.jar:1.3.10.Final-redhat-1] at org.jboss.modules.Module.link(Module.java:1411) [jboss-modules.jar:1.3.10.Final-redhat-1] at org.jboss.modules.Module.relinkIfNecessary(Module.java:1439) [jboss-modules.jar:1.3.10.Final-redhat-1] at org.jboss.modules.ModuleLoader.loadModule(ModuleLoader.java:243) [jboss-modules.jar:1.3.10.Final-redhat-1] at org.jboss.as.server.moduleservice.ModuleLoadService.start(ModuleLoadService.java:71) [jboss-as-server-7.5.19.Final-redhat-2.jar:7.5.19.Final-redhat-2] ... 5 more 中将其出售,请记住 Walmart

我理解RD中1:1,1:n和M:n关系的基础知识,但我不知道如何处理这种复杂性,因为存在多对多的情况。< / p>

如果你能展示一些证明这一点的SQL语句(或DDL),我将非常感激。谢谢!

2 个答案:

答案 0 :(得分:4)

一种公认的常用方法是使用一个表,该表具有用于引用产品的列和用于存储的另一个列。这样的表引用表有很多名称,关联表映射表可以命名一些。

您希望这些效率高,因此请尝试引用一个数字,当然必须唯一地标识它所引用的内容。对于SQLite,默认情况下,表具有一个特殊列,通常是隐藏的,这是一个唯一的数字。它是 rowid ,并且通常是访问行的最有效方式,因为SQLite在设计时就是这种常见用法。

SQLite允许您为每个表创建一个列,该列是 rowid 的别名,您只需提供列INTEGER PRIMARY KEY,通常您可以命名列ID。

因此,使用这些参考表将有一个产品ID列和另一个商店ID用于产品/商店的每个组合。

作为示例,使用以下方式创建了三个表(存储产品和引用/映射表): -

CREATE TABLE IF NOT EXISTS _products(id INTEGER PRIMARY KEY, productname TEXT, productcost REAL);
CREATE TABLE IF NOT EXISTS _stores (id INTEGER PRIMARY KEY, storename TEXT);
CREATE TABLE IF NOT EXISTS _product_store_relationships (storereference INTEGER, productreference INTEGER);
INSERT INTO _products (productname,productcost) VALUES
    ('thingummy',25.30),
    ('Sky Hook',56.90),
    ('Tartan Paint',100.34),
    ('Spirit Level Bubbles - Large', 10.43),
    ('Spirit Level bubbles - Small',7.77)
;
INSERT INTO _stores (storename) VALUES
    ('Acme'),
    ('Shops-R-Them'),
    ('Harrods'),
    ('X-Mart')
;

结果表格为: -

enter image description here enter image description here

  • _product_store_relationships 将为空

可以使用以下方式将产品放入商店(例如) -

-- Build some relationships/references/mappings
INSERT INTO  _product_store_relationships VALUES
    (2,2), -- Sky Hooks are in Shops-R-Them
    (2,4), -- Sky Hooks in x-Mart
    (1,3), -- thingummys in Harrods
    (1,1), -- and Acme
    (1,2), -- and Shops-R-Them
    (4,4), -- Spirit Level Bubbles Large in X-Mart
    (5,4), -- Spiirit Level Bubble Small in X-Mart
    (3,3) -- Tartn paint in Harrods
;

_product_store_relationships 将是: -

enter image description here

如下所示的查询将列出按商店排序的商店中的产品,然后列出产品: -

SELECT storename, productname, productcost FROM _stores 
JOIN _product_store_relationships ON _stores.id = storereference 
JOIN _products ON _product_store_relationships.productreference = _products.id
ORDER BY storename, productname
;

结果输出为: -

enter image description here

此查询仅列出产品名称包含 s S 的商店(类似于区分大小写),根据productcost排序的输出 ASC 结束订单,然后是商店名称,然后是产品名称: -

SELECT storename, productname, productcost FROM _stores 
JOIN _product_store_relationships ON _stores.id = storereference 
JOIN _products ON _product_store_relationships.productreference = _products.id
WHERE productname LIKE '%s%'
ORDER BY productcost,storename, productname 
;

输出: -

enter image description here

扩展上述内容以考虑各州。

2个新表state和store_state_reference

  • 虽然没有真正需要参考表(商店只会在一个州,除非你认为商店连锁店是商店,在这种情况下,这也可以应付)

SQL可能是: -

CREATE TABLE IF NOT EXISTS _states (id INTEGER PRIMARY KEY, statename TEXT);
INSERT INTO _states (statename) VALUES
    ('Texas'),
    ('Ohio'),
    ('Alabama'),
    ('Queensland'),
    ('New South Wales')
;
CREATE TABLE IF NOT EXISTS _store_state_references (storereference, statereference);
INSERT INTO _store_state_references VALUES
    (1,1),
    (2,5),
    (3,1),
    (4,3)
;

如果运行以下查询: -

SELECT storename,productname,productcost,statename
FROM _stores
JOIN  _store_state_references ON _stores.id = _store_state_references.storereference
JOIN _states ON _store_state_references.statereference =_states.id
JOIN _product_store_relationships ON _stores.id = _product_store_relationships.storereference
JOIN _products ON _product_store_relationships.productreference = _products.id
WHERE statename = 'Texas' AND productname = 'Sky Hook'
;

输出结果为: -

enter image description here

没有WHERE子句: -

enter image description here

使商店-R-Them在所有州都有存在: -

以下内容将使Stores-R-Them在所有州都有存在: -

INSERT INTO _store_state_references VALUES
   (2,1),(2,2),(2,3),(2,4)
;

现在德克萨斯州的Sky Hook将导致: -

enter image description here

  • 注意这只涵盖了主题的基础知识。

答案 1 :(得分:2)

您需要创建产品,状态和商店的组合映射表tbl_product_states_stores,它将存储产品,状态和商店的映射。列将为idproduct_idstate_idstores_id