3

应该有一个管理面板的子系统,不同的用户可以管理他们的产品,但在影响主产品表之前,每个更改都应该得到管理员的批准。有三个主表:

  1. 产品:存储最终批准并在整个系统中使用的产品
  2. Changes_versions :与 Product Table 具有一对多关系的表,表示每个更改版本由谁提交,何时提交,并由管理员批准/拒绝或仍处于 Pending 状态。表结构如下:

    CREATE TABLE `changes_versions` (
      `xid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `xcreated_date` datetime DEFAULT NULL,
      `xupdated_date` timestamp NULL DEFAULT NULL,
      `xversion` int(11) DEFAULT NULL,
      `xobject_id` int(11) DEFAULT NULL,
      `xobject_type` varchar(255) DEFAULT NULL,
      `xstate` enum('PENDING','ACCEPTED','REJECTED') DEFAULT 'PENDING',
      PRIMARY KEY (`xid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=165 DEFAULT CHARSET=utf8
    
  3. 更改:与 Changes_versions 表具有一对多关系的表,该表保留主表的每一列更改记录(这里我指的是产品表),并且通过管理员批准 change_version 记录,其相关更改记录将放置在主表列中。表结构如下:

    CREATE TABLE `changes` (
      `xid` int(11) unsigned NOT NULL AUTO_INCREMENT,
      `xcreated_date` datetime DEFAULT NULL,
      `xcreated_by` varchar(255) DEFAULT NULL,
      `xupdated_date` timestamp NULL DEFAULT NULL,
      `xupdated_by` varchar(255) DEFAULT NULL,
      `xversion_id` int(11) DEFAULT NULL,
      `xcolumn_name` varchar(255) DEFAULT NULL,
      `xcolumn_value` varchar(255) DEFAULT NULL,
      `xstate` enum('PENDING','ACCEPTED','REJECTED') DEFAULT 'PENDING',
      `xadmin_review` text,
      PRIMARY KEY (`xid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=764 DEFAULT CHARSET=utf8
    

使用这个系统和表模式,我处理了记录更改,用户获取记录列表,如果用户有任何 Pending 状态 change_version,系统将提取其相关更改记录并将它们放在获取的产品行的右列中(临时只是用于显示),因此即使用户有任何未决状态更改,他/她也可以在他/她的面板中看到其更改(不是主系统,只有他/她的面板)。

问题在于插入新记录,我可以创建一个 change_version 记录并将所有用户数据保存到指向新 change_vesrion 记录的更改表中,但 change_vesrion 记录未连接到任何产品记录,因为没有记录。

请注意,基于系统复杂性和当前稳定性,我不想在产品表中添加任何列来表明这是一个临时记录。

所以我想要一个策略来处理问题,比如当我在用户面板中对产品进行分页并用最后的 PENDING 更改填充它们时,没有插入记录的产品记录来填充更改,因此用户无法看到他/她以前插入的产品。


我还应该注意到,对于这个问题,这个表结构可能看起来很复杂。这个结构很复杂,因为 changes_vesrsion 和 changes 表保存并显示了许多具有不同结构的表的历史和管理员批准过程。

4

3 回答 3

2

让我先用我的话描述你的问题(如果我错了,请纠正我)。

您的系统中有不同的项目(如产品),每种项目类型都有一个(InnoDB)表。每个项目表都有一个 AUTO_INCREMENT 列(如id)。您有一个项目版本表 ( changes_versions) 来存储特定项目的不同版本。项目由列标识

  • xobject_type(如“产品”)引用一个表
  • xobject_id这是一个引用上表PK的“多态外键”

问题:当用户创建一个新项目时,它不应该被插入到项目表中,但是你需要一个引用来存储在xobject_id列中。

一个可能的解决方案:通过在事务中插入和删除一行来“保留”ID。

例子:

start transaction;
insert into products(column_1, column_2) values ('value_1', 'value_2');
delete from products where id = last_insert_id();
select last_insert_id();
commit;

你会得到什么:

  • 插入的行将永远不会对其他用户可见,因为它在同一事务中被删除。
  • last_insert_id()仍会从删除的行返回自动生成的 ID;
  • 该 ID 将被“烧毁”,因此引擎将永远不会再生成它。
  • 当管理员接受该项目时,您仍然可以手动插入该 ID。
  • 不需要更改数据库模式。

演示:http ://rextester.com/IJB42705

于 2017-05-31T18:21:00.010 回答
2

对此的解决方案是创建所有表,当用户在changes_version表中创建产品时,应该有一个mysql 事件定期检查表中的每条记录product并将其与changes_version表匹配。changed_version如果在表内发现任何更改或新插入,product则应相应地插入/更新表。

修改后的解决方案:

您可以通过在用户登录时将用户记录插入产品表changes_version并在注销时将其删除来实现它。这适用于尚未移入product表格的产品,您可以通过查询进行检查。

如果您有前端源,那么您可以仅向用户显示记录,并在获得批准changes_version后通过触发器将其移动到表中。product

于 2017-06-04T09:08:50.967 回答
1

我认为 SQL View 在这里可以很方便,更改您的表名并添加一个标志字段,该字段标记临时行,然后创建一个名称为 Product 的视图,并在 View 中排除该字段和该字段标记的行,由此方式您的原始表(现在转换为视图)将保持不变

于 2017-05-29T09:21:39.957 回答