简体   繁体   English

是否有用于表示来自不同表的多个对象的规范化形式?

[英]Is there a normalized form for representing several objects from different tables?

For a system I am currently building, the following two scenarios occur: 对于我当前正在构建的系统,会出现以下两种情况:

  1. My permissions system is the perennial favorite of attaching permissions to roles, and roles to users, but with a twist: permissions may be applied to any asset at any tier, and there are 4 "Tiers", numbered 0 through 3. As such, the role assignment table is 5 fields long: asset tier, asset ID, role ID, user ID, and a flag for "disabled." 我的权限系统是将角色和角色的权限附加到用户的常年最爱,但有一个转折:权限可以应用于任何层的任何资产,并且有4个“层”,编号为0到3.因此,角色分配表长度为5个字段:资产层,资产ID,角色ID,用户ID和“已禁用”标志。 This "Tier/ID" system is also used in assigning users to a "Home Asset". 该“Tier / ID”系统还用于将用户分配给“Home Asset”。

    The unfortunate side effect of this system is that it is generally far simpler to resolve my these asset references in the application itself, instead of in the SQL (I know it would be possible to do, but it would result in some seriously ugly queries). 这个系统的不幸的副作用是,在应用程序本身中解析我的这些资产引用通常要简单得多,而不是在SQL中(我知道它可以这样做,但它会导致一些严重的丑陋查询) 。 Is there a better way to represent this sort of relationship? 有没有更好的方式来表示这种关系? Is this an acceptable way of representing this relationship? 这是表达这种关系的可接受方式吗?

    Side note: the tables for the assets themselves (they are hierarchal) are normalized, with foreign key references pointing from child to parent (eg Tier 3 contains info about Tier 2, etc), so once a single asset is pinned down it is very simple to locate its children and ancestors. 旁注:资产本身的表(它们是分层的)是规范化的,外键引用从子节点指向父节点(例如,第3层包含有关第2层的信息等),因此一旦单个资产被固定,它就非常很容易找到它的孩子和祖先。

  2. Similar problem, but different data context: At the lowest tier, devices can be "attached." 类似的问题,但不同的数据上下文:在最低层,设备可以“附加”。 Devices are also allowed to be placed onto a graphical representation (like a map), and their arrangement information is stored in the database. 还允许将设备放置在图形表示(如地图)上,并将它们的排列信息存储在数据库中。 Graphical references (also called "points") should point at a real device, but a real device may not point at a graphical reference. 图形引用(也称为“点”)应指向真实设备,但实际设备可能不指向图形引用。

    At present, there is a single reference table to all "points" (which represent devices) with information for their display layout, location, size, etc. I can identify three possible things to do from here: 目前,所有“点”(代表设备)都有一个参考表,其中包含显示布局,位置,大小等信息。我可以从这里确定三个可能的事情:

    1. Create a series of normalized tables to represent individual devices, and use a similar "device type / device ID" system to look them up, and store this information in the "points" table; 创建一系列规范化表来表示各个设备,并使用类似的“设备类型/设备ID”系统查找它们,并将此信息存储在“点”表中; this will still require the application to do intermediary work in resolving those references to actual devices in their respective tables 这仍然需要应用程序在解析对各自表中的实际设备的引用时进行中间工作
    2. Create a series of normalized tables, and point them at the "points" table; 创建一系列规范化表,并将它们指向“点”表; this solution probably won't require the application to dereference the points data, but will require that all device tables be scanned for any Tier 3 object. 此解决方案可能不需要应用程序取消引用点数据,但需要扫描所有设备表以查找任何第3层对象。
    3. Using the points table as a guideline, add all of the relevant display data to each respective normalized table. 使用点表作为指导,将所有相关显示数据添加到每个相应的标准化表中。 While this would prevent having to resolve any lookups at all, it will still require that I scan every device table, and is also extremely intolerant to any changes in how the points data must be stored compared to the other solutions. 虽然这可以防止必须完全解决任何查找,但仍然需要扫描每个设备表,并且与其他解决方案相比,对于必须存储点数据的方式的任何变化也非常不容忍。

    Is this problem already solved and I just didn't get the memo? 这个问题已经解决了,我只是没有得到备忘录? Is there a standard design addressing this problem, or should I just assume that I will have to resolve these references myself? 是否有解决此问题的标准设计,或者我应该假设我必须自己解决这些引用?

Note: With respect to problem two, I have deemed the following two solutions to be horrible and I will not consider them (barring some crazy, amazing evidence that it is the best way, which I'm fairly sure it isn't): 注意:关于问题二,我认为以下两种解决方案是可怕的,我不会考虑它们(除非有一些疯狂的,令人惊讶的证据表明它是最好的方式,我相当确定它不是):

  1. Store all the information about each device (in a serialized array or some such mechanism) in the points table itself. 在点表本身中存储有关每个设备的所有信息(在序列化数组或某些此类机制中)。 This has the obvious problem of being completely unsearchable and defying normal form 这具有明显的问题,即完全无法搜索并且违反正常形式
  2. Store all devices in a single, generic table. 将所有设备存储在单个通用表中。 Unfortunately, these devices are all extremely different in the type of data they provide, as well as how they must be accessed, and doing so in one table would require, last time I tried working it out on paper, at least 30 (and probably more) columns, more than half of which would be null for every row. 不幸的是,这些设备在它们提供的数据类型以及它们必须如何被访问方面都有很大的不同,并且在一个表格中这样做需要,上次我尝试在纸上完成它,至少30(并且可能更多)列,其中一半以上的每行都为空。

Any solutions are requested and appreciated, though I am specifically looking for existing patterns and/or normalized schemas which address this issue, if any exist. 请求和赞赏任何解决方案,但我特别寻找解决此问题的现有模式和/或规范化模式(如果存在)。 If you know for a fact that it is the correct answer, "No" will suffice and I will continue to use the application layer to resolve these references. 如果您知道这是正确答案的事实,“否”就足够了,我将继续使用应用程序层来解析这些引用。 It has not been a problem yet, I just prefer to know I'm not forging a path in the wrong direction when someone has already solved this/these problem(s). 它还没有成为问题,我只是想知道当有人已经解决了这个/这些问题时,我并没有在错误的方向上开辟道路。 Thanks in advance. 提前致谢。

EDIT: Permissions/Asset Schema 编辑:权限/资产架构

Tier 0 is actually implied and not in the database, but some things are registered as Tier 0 (Asset ID 0) 第0层实际上是隐含的,而不是在数据库中,但有些东西被注册为第0层(资产ID 0)

Tier 1: 第1层:

id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
disabled tinyint(1) unsigned not null,

Tier 2: 2级:

id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier1(id)

Tier 3: 第3层:

id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier2(id)

Permissions: 权限:

id int(5) unsigned not null primary key auto_increment,
permission_key varchar(16) not null,
permission_desc varchar(128) not null

Roles: 角色:

id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
tier1_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
foreign key (tier1_id) references tier1(id)

Role_Permissions: Role_Permissions:

role_id int(5) unsigned not null,
permission_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (role_id, permission_id),
foreign key (role_id) references roles(id),
foreign key (permission_id) references permissions(id)

User_Role_Permissions: User_Role_Permissions:

tier_id tinyint(1) unsigned not null,
asset_id int(5) unsigned not null,
user_id int(5) unsigned not null,
role_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (tier_id, asset_id, user_id, role_id),
foreign key (user_id) references users(id),
foreign key (role_id) references roles(id)

Have you considered breaking up your permissions table into a set of tables that each apply to a separate table of objects, for instance tier_1_assets and tier_1_permissions, and tier_2_assets and tier_2_permissions. 您是否考虑将权限表分解为一组表,每个表都应用于单独的对象表,例如tier_1_assets和tier_1_permissions,以及tier_2_assets和tier_2_permissions。 This will make it simpler to query the permissions for a tier of assets, but more complex to query for all the permissions of a user (this is a trade off). 这将使查询资产层的权限变得更加简单,但查询用户的所有权限会更复杂(这是一种权衡)。

I would also challenge the assumption that a relational database is the right storage medium for your data. 我还要质疑关系数据库是数据的正确存储介质的假设。 It may indeed be, but may also not be. 它可能确实是,但也可能不是。 (PHP may limit freedom in that respect). (PHP可能会限制这方面的自由)。

If your data set is small, why not save it to a single serialized file, and have a small server that keeps it in memory and provides a query interface? 如果您的数据集很小,为什么不将它保存到单个序列化文件中,并且有一个小服务器将它保存在内存中并提供查询接口? I am sure there are good reasons why not. 我相信没有充分的理由。 (In addition to being in PHP) (除了在PHP中)

Have you considered multiple point tables for your second problem? 您是否考虑过第二个问题的多个积分表? It may feel like a repetition, but it does make life simpler for some kinds of look ups, and is normalized when you consider each foreign key reference as a different type of object (you get to use foreign key checks on them when the tables are separated). 它可能感觉像是重复,但它确实使某些类型的查找变得简单,并且当您将每个外键引用视为不同类型的对象时会被规范化(当表是对象时,您可以对它们使用外键检查)隔开)。

The multiplicity of the relationships between objects should tell you where to put your keys and references: one-to-many -> (key <- foreign key); 对象之间关系的多样性应告诉您将键和引用放在何处:一对多 - >(键< - 外键); many-to-many -> (key <- link-table -> key); many-to-many - >(key < - link-table - > key); one-to-optional -> (key <- foreign key). one-to-optional - >(key < - 外键)。

I do not know of any patterns that match your problem as it was stated. 我不知道任何与你的问题相符的模式。 But I have noticed that most generic solutions to avoid creating another table get really hard to manage very quickly. 但我注意到,避免创建另一个表的大多数通用解决方案很难快速管理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM