Mysql 如何避免在字段中输入互斥数据
我试图限制字段中的输入错误。我正在建设的网站包含汽车数据 一辆汽车可以有一个列表中的多个设备(空调、ABS、真皮座椅等),我希望以某种方式防止数据输入出错,或者至少将其最小化 第一种错误情况是为两个或多个互斥设备输入数据。例如,一辆汽车不能有手动空调和自动空调以及自动空调两个区域。车里只能有一个 第二种错误情况是在没有先决条件的情况下为设备输入数据。例如,在没有所需ABS的情况下进入紧急制动辅助系统(BA)。汽车可以有ABS 没有BA,但BA将只存在于配备ABS的汽车中 输入数据的表格是直接的。每辆车(版本号)都有多个设备(饰件)或饰件号。版本id和修剪id分别是FK到表格版本和修剪。因此,不存在trim_id或version_id的错误已经在VersionTim表中得到处理 表versiontrim(我希望在其中最小化数据错误) 表饰件:Mysql 如何避免在字段中输入互斥数据,mysql,Mysql,我试图限制字段中的输入错误。我正在建设的网站包含汽车数据 一辆汽车可以有一个列表中的多个设备(空调、ABS、真皮座椅等),我希望以某种方式防止数据输入出错,或者至少将其最小化 第一种错误情况是为两个或多个互斥设备输入数据。例如,一辆汽车不能有手动空调和自动空调以及自动空调两个区域。车里只能有一个 第二种错误情况是在没有先决条件的情况下为设备输入数据。例如,在没有所需ABS的情况下进入紧急制动辅助系统(BA)。汽车可以有ABS 没有BA,但BA将只存在于配备ABS的汽车中 输入数据的表格是直接的。
trim_id trim trimtype
表格版本
version_id model_id version active bodytype places motor_id etc...
非常感谢您的帮助。对于每个选定的装饰,
检索互斥修剪集。
检查是否也选择了其中任何一项。
检索先决条件修剪集。
检查是否也选择了其中的每一项。
创建表先决条件(
trim_id1 int not null引用trims(trim_id),
trim_id2 int not null引用trims(trim_id),
主键(trim_id1,trim_id2)
);
创建表格专用项(
独占组int不为空,
修剪id int not null引用修剪(修剪id),
主键(专用组,微调id),
索引(修剪id,独占组)
);
--检索所选TRIM的所有先决条件
选择p.trim_id1、p.trim_id2
从第五版开始
内部联接版本在vt.version\u id=v.version\u id上运行
p.trim_id上的内部连接先决条件p=vt.trim_id
其中v.version_id=?;
--检索所选修剪的所有互斥修剪
选择vt.trim_id作为trim_id 1,选择e2.trim_id作为trim_id 2
从第五版开始
内部联接版本在vt.version\u id=v.version\u id上运行
e1.trim\u id=vt.trim\u id上的内部连接专用e1
e2上的内部联接独占e2。独占组=e1。独占组
其中e1.trim_id e2.trim_id
和v.version_id=?;
您可以更进一步,返回冲突:
-- Retrieve any missing prerequisites of the selected trims
select p.trim_id1, p.trim_id2
from versions v
inner join versiontrim vt1 on vt1.version_id = v.version_id
inner join prerequisites p on p.trim_id1 = vt1.trim_id
left join versiontrim vt2
on vt2.version_id = v.version_id
and vt2.trim_id = p.trim_id2
where vt2.version_id is null
and v.version_id = ?;
-- Retrieve any selected mutually exclusive trims
select vt.trim_id as trim_id1, e2.trim_id as trim_id2
from versions v
inner join versiontrim vt on vt.version_id = v.version_id
inner join exclusives e1 on e1.trim_id = vt.trim_id
inner join exclusives e2 on e2.exclusive_group = e1.exclusive_group
inner join versiontrim vt2 on vt2.version_id = v.version_id
where e1.trim_id <> e2.trim_id
and vt2.trim_id = e2.trim_id
and v.version_id = ?;
--检索所选饰件缺少的任何先决条件
选择p.trim_id1、p.trim_id2
从第五版开始
内部联接版本vt1上的IM vt1.version\u id=v.version\u id
p.trim_id上的内部连接先决条件p=vt1.trim_id
左连接版本TM vt2
在vt2.version\u id=v.version\u id上
和vt2.trim_id=p.trim_id2
其中vt2.version\u id为空
和v.version_id=?;
--检索任何选定的互斥修剪
选择vt.trim_id作为trim_id 1,选择e2.trim_id作为trim_id 2
从第五版开始
内部联接版本在vt.version\u id=v.version\u id上运行
e1.trim\u id=vt.trim\u id上的内部连接专用e1
e2上的内部联接独占e2。独占组=e1。独占组
内部联接版本vt2上的IM vt2.version\u id=v.version\u id
其中e1.trim_id e2.trim_id
和vt2.trim_id=e2.trim_id
和v.version_id=?;
如果要在数据库级别对这些依赖项进行建模,应将这些选项视为一个不同的实体
由于您当前的结构模拟了N-N关系,因此它还允许将同一选项多次附加到给定的版本
。对于所有选项,您应采用与下面相同的方法
互斥期权构成期权的“类型”。例如,您描述的空调选项是“空调类型”
为此,创建一个新实体(例如,aircond\u type
):
这显然是不切实际的,或者至少是不灵活的。一个简单的验证触发器可以进行检查,并在没有“ABS”选项的情况下防止“BA”选项的归属
或者,对于这个简单的1-1依赖关系,您可以将“BA”选项视为“ABS”选项的变体。这样,您将有三个“刹车”选项:“标准”、“ABS”、“带BA的ABS”。将业务需求与数据混合在一起……这类事情应该由GUI应用程序或应用程序服务器处理,而不是数据库。您可以使用存储过程插入数据,而不是直接访问表,在这种情况下,您可以在实际插入或插入任何先决条件之前进行任何检查。我在想你的第一句话。在某种程度上,数据库中的所有内容都是由业务需求驱动的,在特定情况下,它与数据的一致性有关。根据存储过程,我仍然需要被介绍给它。在数据库级别进行一些检查是可以的,但在理想情况下,这些检查应该是一个以防万一的防线,你永远不会真正击中它。您的UI和/或应用程序代码应该在更高的级别上执行类似的检查,以提供更好的用户体验,而不仅仅是将用户输入的内容推送到数据库中,然后捕获数据库错误。谢谢jcsanyi,但我不能再多说了。没有其他人能在更高或更低的层次上拿着这个包。后台人员将通过表单或其他方式输入数据,并会犯错误,如果不被发现,我的客户(即网站访问者)将看到这些错误。对我来说,创建或找到一个新的系统来防止这些错误是毫无意义的。mysql中肯定有工具可以做到这一点。顺便说一下,我喜欢Markus Jarderot的建议。这是关于解决问题,而不是把问题传给别人。谢谢。就你对同一个选项被多次附加到同一个版本上的评论而言,我没有提到这一点
create table prerequisites (
trim_id1 int not null references trims ( trim_id ),
trim_id2 int not null references trims ( trim_id ),
primary key ( trim_id1, trim_id2 )
);
create table exclusives (
exclusive_group int not null,
trim_id int not null references trims ( trim_id ),
primary key ( exclusive_group, trim_id ),
index ( trim_id, exclusive_group )
);
-- Retrieve all prerequisites of selected trims
select p.trim_id1, p.trim_id2
from versions v
inner join versiontrim vt on vt.version_id = v.version_id
inner join prerequisites p on p.trim_id1 = vt.trim_id
where v.version_id = ?;
-- Retrieve all mutually exclusive trims of selected trims
select vt.trim_id as trim_id1, e2.trim_id as trim_id2
from versions v
inner join versiontrim vt on vt.version_id = v.version_id
inner join exclusives e1 on e1.trim_id = vt.trim_id
inner join exclusives e2 on e2.exclusive_group = e1.exclusive_group
where e1.trim_id <> e2.trim_id
and v.version_id = ?;
-- Retrieve any missing prerequisites of the selected trims
select p.trim_id1, p.trim_id2
from versions v
inner join versiontrim vt1 on vt1.version_id = v.version_id
inner join prerequisites p on p.trim_id1 = vt1.trim_id
left join versiontrim vt2
on vt2.version_id = v.version_id
and vt2.trim_id = p.trim_id2
where vt2.version_id is null
and v.version_id = ?;
-- Retrieve any selected mutually exclusive trims
select vt.trim_id as trim_id1, e2.trim_id as trim_id2
from versions v
inner join versiontrim vt on vt.version_id = v.version_id
inner join exclusives e1 on e1.trim_id = vt.trim_id
inner join exclusives e2 on e2.exclusive_group = e1.exclusive_group
inner join versiontrim vt2 on vt2.version_id = v.version_id
where e1.trim_id <> e2.trim_id
and vt2.trim_id = e2.trim_id
and v.version_id = ?;
aircond_type:
+----+-----------+
| id | label |
+----+-----------+
| 1 | none |
+----+-----------+
| 2 | manual |
+----+-----------+
| 3 | automatic |
+----+-----------+
| 4 | bi-zone |
+----+-----------+
CREATE TABLE version_has_abs (
version_id INT NOT NULL PRIMARY KEY,
CONSTRAINT version_fk FOREIGN KEY version_fk_idx(version_id)
REFERENCES version(version_id)
);
CREATE TABLE version_has_ba (
version_id INT NOT NULL PRIMARY KEY,
CONSTRAINT version_fk FOREIGN KEY version_fk_idx(version_id)
REFERENCES version_has_abs(version_id)
);