(在那之前,我为我糟糕的英语道歉) 我有这样的研究案例:
我目前在使用Web应用程序时出现问题。我为某个公司制作了一个Web应用程序。我使用CodeIgniter 3制作了应用程序。
我使用Maria DB构建了数据库。对于每个表中的id,我使用 Auto-increment id 作为每个表的应用程序数据库。我通常将Web应用程序部署到云服务器(有时公司有自己的专用服务器,但有时却没有)。有一天,有一家公司,他们不想将我之前制作的应用程序部署到云端(出于安全目的,他们说)。
该公司希望将该应用程序部署到员工的个人电脑上,而每个员工的电脑不相互连接(即独立的个人电脑/个人电脑/员工的笔记本电脑)。他们说,他们会每5个月将员工个人电脑的所有数据收集到公司的数据中心,当然数据中心也没有连接到互联网。我告诉他们这不是存储数据的好方法。 (因为当我尝试将所有数据合并为一个数据时,数据将会重复,因为我的每个表的列ID都在自动增量ID 中,并且它是主键< /强>)。不幸的是,公司仍然希望以这种方式保留应用程序,我不知道如何解决这个问题。
他们至少有10名员工会使用此网络应用。据此,我必须亲自将应用程序部署到10台PC上。
其他信息:每位员工都有自己从公司获得的唯一身份证,我为每位员工制作了 auto_increment id ,如下表所示:
id | employee_id | employee_name |
1 | 156901010 | emp1
2 | 156901039 | emp2
3 | 156901019 | emp3
4 | 156901015 | emp4
5 | 156901009 | emp5
6 | 156901038 | emp6
问题是每当他们从该应用程序填充表单时,某些表不存储员工的id,而是存储来自增量id的新id。
例如 electronic_parts
表。它们具有如下属性:
| id | electronic_part_name | kind_of_electronic_part_id |
如果emp1
填写了网络应用中的表单,则表格的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | switch | 1 |
如果emp2
填写了网络应用中的表单,则表格的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | duct tape | 10 |
当我试图将表的内容合并到数据中心时,它会因为重复的ID而崩溃。
当我在其他表中考虑我的外键时,情况变得更糟......例如customer_order
表。
customer_order
列的表格如下所示(只是一个示例,不是实际的表格,但类似)。
|id | customer_name | electronic_parts_id | cashier(a.k.a employee_id, the increment id one, not the id that employee got from a company as i described above ) |
| 1 | Henry | 1 | 10 |
| 2 | Julie | 2 | 9 |
有谁知道如何解决这个问题?或者有人可以建议/推荐一些解决这个问题的好方法吗?
注意:每个员工都有自己的应用程序数据库,因此数据库不是集中式的,它是一个独立的数据库,这意味着,我必须逐个将数据库安装到员工的PC上
答案 0 :(得分:9)
这是一个非传统的情况,你可以有一个非传统的解决方案。
我可以建议你解决这个问题的两种方法。
不使用自动增量主键生成UUID而是将其用作主键。关于重复的可能性 在随机UUID中:仅在每秒生成10亿UUID之后 未来100年
在CodeIgniter中,您可以使用以下代码段执行此操作。
$this->db->set('id', 'UUID', FALSE);
这将生成一个36个字符的十六进制密钥(带有4个破折号) 包括在内)。
ac689561-f7c9-4f7e-be94-33c6c0fb0672
正如您所看到的,它使用CodeIgniter DB在字符串中有破折号 函数将使用破折号将其插入数据库中,它仍然是 将工作。如果它看起来不干净,你可以删除和 将字符串转换为32-char键。
您可以在[CodeIgniter]的帮助下使用以下功能 UUID图书馆] [1]。
function uuid_key {
$this->load->library('uuid');
//Output a v4 UUID
$id = $this->uuid->v4();
$id = str_replace('-', '', $id);
$this->db->set('id', $id, FALSE);
}
现在我们有一个32字节的密钥,
ac689561f7c94f7ebe9433c6c0fb0672
另一种解决这种情况的非常规方法是 添加函数以记录所有已处理的Insert,Update,Delete查询 在站点中本地文件。通过这种方式,在每个地方 实现将生成一个具有实际列表的日志文件 以正确的顺序顺序修改数据库的查询。
在任何时候,数据库的状态都是结果 所有这些查询的集合,直到该日期为止。
因此,当您准备好从中收集数据时,每5个月 员工个人电脑,而不是采取数据转储,采取这个 带有所有查询日志的文件。(注意:这样的查询日志不会有 自动递增ID,因为它只会在实时创建时生成 它是针对数据库执行的。 )
使用此类文件将数据导入数据中心。这不会 冲突因为它会在您的数据中心中生成自动增量 即时的。 (希望您不必将本地链接到数据中心 在未来的任何时间点)
答案 1 :(得分:4)
是否在其他任何表中使用id
?它可能会涉及JOIN
。如果是这样,你就会解决这个问题。
如果id
未在其他任何地方使用,则值无关紧要,行可以重新编号。这可以通过将各种来源的数据加载到同一个表中来完成(粗略地说),但不在加载中包含id
。
或者,如果存在UNIQUE
的其他列(或列组合),则将 <{em> PRIMARY KEY
并删除id
哪种情况适用?我们可以更详细地追求。请为SHOW CREATE TABLE
提供相关的任何表格。
在我的第一种情况下(其中id在其他地方用作FK),请执行以下操作:
使用id
将行插入表中时,请将值递增足以避免与现有ID冲突。然后做(在同一交易中):
UPDATE the_other_table SET fk_id = fk_id + same_increment.
根据需要对每个其他表和每个id重复一次。
答案 2 :(得分:2)
我认为您的问题来自您的数据库 ...您没有很好地设计它。 如果你有两个差异用户的ID,那么它就是错误。
如果您在数据库中创建了自己的ID字段唯一,那么两位员工就不会拥有相同的ID,因此您的问题出在您的表格设计中。
只需启动您的ID字段,您的问题就会得到解决。
CREATE TABLE [YOUR TABLE NAME](
[ID] int NOT NULL IDENTITY(1,1) PRIMARY KEY,
....
答案 3 :(得分:0)
id是否需要是整数?如果不是,你可以在id上使用前缀,这样每个员工的输入一般都是唯一的。这意味着你必须放弃自动增量并只计算表格数据(假设你没有删除任何记录。)
答案 4 :(得分:0)
你可能需要用PHP编写一个代码来处理这个问题。如果其他表已经基于唯一/主键,那么它就好了。
您也可以在导入后执行此操作。 像这样 Find duplicates in the same table in MySQL