EAV 模型 - 如何限制产品属性?

EAV model - How to restrict product properties?

我的数据库结构如下,实现了一个简单的 EAV 模型(见图):

我的 product 有一个 type,它通过连接点 table 限制 prop_names,可用于此产品。这里一切都很清楚。 但: 然后我添加了 prop_values table 来保留每个产品的属性值。它引用了 productsprod_skuprop_namesprop_id。问题来了:可以向任何产品添加任何属性 - 甚至是该产品类型不允许的属性。此外,可能存在重复 - 单个产品的两个或多个相同属性。

有什么方法可以在数据库级别限制它吗?

在@BillKarvin 的回答后,我尝试了下面的 CREATE 代码,但在创建最后一个 table (property_values).[=22 时失败并出现 'Foreign key constraint is incorrectly formed' 错误=]

我发现了我的错误 - 我忘记给 products table 添加 KEY。以下是我的代码的更正(工作)版本:

CREATE TABLE product_types (
  id INT PRIMARY KEY,
  product_type varchar(50) NOT NULL,
  block_css_id varchar(50) NOT NULL,
  block_description varchar(50) NOT NULL
);

CREATE TABLE products (
  sku varchar(50) PRIMARY KEY,
  name varchar(50) NOT NULL,
  price decimal(20,2) unsigned NOT NULL,
  id_product_type INT NOT NULL,
  FOREIGN KEY (id_product_type) REFERENCES product_types (id),
  KEY (sku, id_product_type)
);

CREATE TABLE property_names (
  id INT PRIMARY KEY,
  property_name varchar(50) NOT NULL,
  property_css_id varchar(50) NOT NULL,
  property_input_name varchar(50) NOT NULL
);

CREATE TABLE junction_ptype_propname (
  id_productt_type INT NOT NULL,
  id_property_name INT NOT NULL,
  PRIMARY KEY (id_productt_type, id_property_name),
  FOREIGN KEY (id_productt_type) REFERENCES product_types (id),
  FOREIGN KEY (id_property_name) REFERENCES property_names (id)
);

CREATE TABLE property_values (
  id INT NOT NULL PRIMARY KEY,
  product_sku varchar(50) NOT NULL,
  property_id INT NOT NULL,
  property_value decimal(20,2) NOT NULL DEFAULT 0.00,
  id_prod_type INT NOT NULL,
  UNIQUE KEY (product_sku, property_id),
  FOREIGN KEY (product_sku, id_prod_type) REFERENCES products (sku, id_product_type),
  FOREIGN KEY (property_id, id_prod_type) REFERENCES junction_ptype_propname (id_property_name, id_productt_type)
);

Also, there can be duplications - two or more same properties for a single product.

使用 UNIQUE 防止重复

w3schools.com - UNIQUE

我会这样设计:

与您的模型有一些重要区别:

  • prop_values(prod_sku, prop_id) 上有一个唯一键,因此每个产品 sku 只能有给定 属性 的一个实例。

  • prop_values 有一个 prod_type 列,这引用 products,同时使用两个列 (sku, prod_type).

  • prop_values 有一个指向 junction_ptype_propname 而不是 prop_name.

    的复合外键

现在 prop_values 中的 prod_type 每行可以有一个值,并且它必须在 products table 和 junction_ptype_propname table。因此,它被限制为给定产品的有效 属性,以及产品类型的有效 属性。因此,您不能将 属性 添加到对于该产品类型不合法的产品。

这是 DDL:

create table prod_types (
  id int primary key,
  type_name varchar(30) not null
);

create table products (
  sku varchar(30) primary key,
  name varchar(30) not null,
  type int not null,
  foreign key (type) references prod_types(id),
  key(sku, type)
);

create table prop_names (
  id int primary key,
  prop_name varchar(30) not null
);

create table junction_ptype_propname (
  id_prop_name int not null,
  id_prod_type int not null,
  primary key (id_prop_name, id_prod_type),
  foreign key (id_prod_type) references prod_types(id),
  foreign key (id_prop_name) references prop_names(id)
);

create table prop_values (
  id int primary key,
  prod_sku varchar(30) not null,
  prod_type int not null,
  prop_id int not null,
  prop_value decimal not null,
  unique key (prod_sku, prop_id),
  foreign key (prod_sku, prod_type) references products(sku, type),
  foreign key (prop_id, prod_type) references junction_ptype_propname(id_prop_name, id_prod_type)
);

这道题很有趣,因为它是使用第五范式的案例。许多关于数据库设计的文章声称不使用超过第三范式的范式。但是你的模型反驳了这一点。