如何在子表中包含数据的表上强制实现唯一性

时间:2016-06-22 01:04:07

标签: mysql sql

在绿色字段项目中,我有一个实体Resource,它有许多子实体Attributes。为了对模式进行建模,我在属性表中创建了一个FK。

资源有nameid,属性有resourceId,属性name和属性value

number of attributesname and value of those attributes必须是资源名称唯一的。我无法在数据库级别强制执行资源的唯一性。

例如, mmg(id:1)有(a:1,b:abc)valid mmg(id:2)有(a:1)valid mmg(id:3)有(a:1,b:abc)not valid

在资源表上,mmg(id:2)完全有效,因为它只有一个属性与其余属性进行比较但mmg(id:3)不是因为它与mmg(id:1)具有相同的属性。它基本上是相同的资源。

mmg(id:3)不应该存在,因为它们具有相同的nameattributes以及same number of attributes。我可以以编程方式强制执行唯一性,但是想知道是否有方法在数据库级别强制执行它,并且可能重新设计表或查询以便更容易和有效地查找。

Resource Table Attributes Table

我需要查询此表并使用其属性查找确切的资源。为此我编写了以下查询并且工作正常(可能没有优化,因为资源可以有很多属性,查询会变得很长):

select * from (SELECT 
    groupedByResourceId.resource_id
FROM
    (SELECT 
        taggedElements.resource_id,
            COUNT(*) AS count1,
            SUM(taggedElements.a_ind) AS a_sum,
            SUM(taggedElements.b_ind) AS b_sum
    FROM
        (SELECT 
        resource_id,
            CASE
                WHEN (name = 'a' AND value = '1') THEN 1
                ELSE 0
            END AS a_ind,
            CASE
                WHEN (name = 'b' AND value = 'abc') THEN 1
                ELSE 0
            END AS b_ind
    FROM
        resource_attribute) AS taggedElements
    GROUP BY 1) AS groupedByResourceId
WHERE
    groupedByResourceId.count1 = 2
        AND groupedByResourceId.a_sum = 1
        AND groupedByResourceId.b_sum = 1) as attr, resource where resource.id = attr.resource_id

注意:平均每个资源最多可包含20个属性(包括0)。

注意:其他表正在使用resourceId。

1 个答案:

答案 0 :(得分:0)

我能想到的最好的方法是在Attributes表,namevalue两列上添加唯一约束:

ALTER TABLE Attributes ADD UNIQUE `idx` (`name`, `value`);

这将确保给定的resource_id必须具有namevalue的唯一组合。

您可以编写一个触发器来检查插入后给定属性的行数是否不超过20。