如何防止 MariaDB 中导入的 table 出现重复 ID?
How do i prevent the duplicate id from the imported table in MariaDB?
(在此之前,我为我糟糕的英语道歉)
我有这样的研究案例:
我的 Web 应用程序目前有问题。我为某家公司制作了一个Web应用程序。我使用 CodeIgniter 3 制作了该应用程序。
我使用 Maria DB 构建了数据库。对于每个 table 中的 ID,我为每个 table 的应用程序数据库使用 Auto-increment id。我通常将网络应用程序部署到云服务器(有时公司有自己的专用服务器,但有时没有)。有一天,有一家公司不想将我之前制作的应用程序部署到云端(他们说是出于安全目的)。
这家公司想将应用程序部署到员工在办公室的个人电脑上,而每个员工的电脑都没有相互连接(即独立 pc/personal computer/employee 的笔记本电脑) .他们说,每5个月,他们会把员工个人电脑的所有数据收集到公司的数据中心,当然数据中心没有连接到互联网。我告诉他们这不是存储数据的好方法。 (因为当我试图将所有数据合并为一个时,数据将是重复的,因为 每个 table 我的列 ID 在 自动增量 ID ,它是一个主键)。不幸的是,公司仍然希望保持这种应用程序,我不知道如何解决这个问题。
他们至少有 10 名员工会使用此 Web 应用程序。据此,我必须亲自将应用程序部署到第10台PC。
附加信息:每个员工都有自己从公司获得的唯一 ID,我为每个员工制作了 auto_increment ID,就像 table 下面:
id | employee_id | employee_name |
1 | 156901010 | emp1
2 | 156901039 | emp2
3 | 156901019 | emp3
4 | 156901015 | emp4
5 | 156901009 | emp5
6 | 156901038 | emp6
问题是每当他们从该应用程序填写表格时,一些 table 不会存储员工的 ID,而是存储来自增量 ID 的新 ID。
例如electronic_parts
table。它们具有如下属性:
| id | electronic_part_name | kind_of_electronic_part_id |
如果 emp1
从网络应用程序填写表格,table 的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | switch | 1 |
如果 emp2
从网络应用程序填写表格,table 的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | duct tape | 10 |
当我尝试将 table 的内容合并到数据中心时,它会崩溃,因为重复的 ID。
当我想到其他 table 中的外键时,情况变得更糟了。例如 customer_order
table.
customer_order
列的 table 如下所示(只是示例,不是实际的 table,但类似)。
|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 |
有谁知道如何解决这个问题?或者有人 suggest/recommend 可以给我一些解决这个问题的好方法吗?
注意:每个员工都有自己的应用程序数据库,所以数据库不是集中的,它是一个独立的数据库,这意味着,我必须将数据库安装到员工的电脑上一个
那个 id
是否在任何其他 table 中使用过?它可能会涉及JOIN
。如果是这样,你在解开 id 时遇到了很大的问题。
如果 id
未在其他任何地方使用,则这些值无关紧要,可以对行重新编号。这将通过将来自不同来源的数据加载到相同的 table 来完成(粗略地说),但是 不 在加载中包含 id
。
或者,如果还有其他列(或列的组合)是 UNIQUE
,则将 that 设为 PRIMARY KEY
并删除id
.
哪种情况适用?我们可以更详细地追究。请为任何相关的 table(s) 提供 SHOW CREATE TABLE
。
在我的第一个案例中(id 在其他地方用作 FK),做这样的事情:
在使用 id
将行插入 table 时,将值增加足够多以避免与现有 ID 冲突。然后做(在同一笔交易中):
UPDATE the_other_table SET fk_id = fk_id + same_increment.
根据需要互相重复 table 和每个 ID。
我认为你的问题出在你的数据库...你没有设计好它。
这是一个 bug 如果你有两个不同用户的 id 。
如果您刚刚在您的数据库中创建了您的 ID 字段唯一,那么两个员工将不会有相同的 ID,所以您的问题出在您的 table 设计中。
只需像这样启动您的 id 字段,您的问题就会得到解决。
CREATE TABLE [YOUR TABLE NAME](
[ID] int NOT NULL IDENTITY(1,1) PRIMARY KEY,
....
这是一个非常规的情况,你可以有一个非常规的解决方案。
我可以建议你两种方法来解决这个问题。
不是对主键使用自动增量,而是生成一个 UUID 并将其用作主键。关于重复概率
在随机 UUID 中:仅在每秒生成 10 亿个 UUID 之后
未来 100 年
在 CodeIgniter 中,您可以使用以下代码片段执行此操作。
$this->db->set('id', 'UUID', FALSE);
这会生成一个 36 个字符的十六进制密钥(带有 4 个破折号
包括)。
ac689561-f7c9-4f7e-be94-33c6c0fb0672
如您所见,字符串中有破折号,使用 CodeIgniter DB
函数将用破折号将其插入数据库中,它仍然
将工作。如果它看起来不干净,您可以删除并
将字符串转换为 32 个字符的键。
您可以在[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
解决这种情况的另一种非常规方法是
添加功能以记录所有已处理的插入、更新、删除查询
在站点中到本地文件。通过这种方式,在每个地方
实施将生成一个包含实际列表的日志文件
随着时间的推移以正确的顺序修改数据库的查询。
在任何时间点,数据库的状态都是
直到那个日期,所有这些查询都发生在过去。
因此,每 5 个月,当您准备好从
员工的个人电脑,而不是采取数据转储,采取这个
包含所有查询日志的文件。(注意:这样的查询日志不会有
自动递增 id,因为它只会在实时创建
它是针对数据库执行的。 )
使用此类文件将数据导入您的数据中心。这不会
冲突,因为它会在您的数据中心生成自动增量
即时的。 (希望您不必 link 本地到数据中心
在未来的任何时间)
id必须是整数吗?如果不是,您可以在 id 上使用前缀,这样每个员工的输入通常都是唯一的。这意味着您必须放弃自动递增,只依靠 table 数据(假设您没有删除任何记录。)
您可能需要在 PHP 中编写代码来处理此问题。如果其他 table 已经在基于 unique/primary 键之后,那就没问题了。
导入后也可以。
像这样
Find duplicates in the same table in MySQL
(在此之前,我为我糟糕的英语道歉) 我有这样的研究案例:
我的 Web 应用程序目前有问题。我为某家公司制作了一个Web应用程序。我使用 CodeIgniter 3 制作了该应用程序。
我使用 Maria DB 构建了数据库。对于每个 table 中的 ID,我为每个 table 的应用程序数据库使用 Auto-increment id。我通常将网络应用程序部署到云服务器(有时公司有自己的专用服务器,但有时没有)。有一天,有一家公司不想将我之前制作的应用程序部署到云端(他们说是出于安全目的)。
这家公司想将应用程序部署到员工在办公室的个人电脑上,而每个员工的电脑都没有相互连接(即独立 pc/personal computer/employee 的笔记本电脑) .他们说,每5个月,他们会把员工个人电脑的所有数据收集到公司的数据中心,当然数据中心没有连接到互联网。我告诉他们这不是存储数据的好方法。 (因为当我试图将所有数据合并为一个时,数据将是重复的,因为 每个 table 我的列 ID 在 自动增量 ID ,它是一个主键)。不幸的是,公司仍然希望保持这种应用程序,我不知道如何解决这个问题。
他们至少有 10 名员工会使用此 Web 应用程序。据此,我必须亲自将应用程序部署到第10台PC。
附加信息:每个员工都有自己从公司获得的唯一 ID,我为每个员工制作了 auto_increment ID,就像 table 下面:
id | employee_id | employee_name |
1 | 156901010 | emp1
2 | 156901039 | emp2
3 | 156901019 | emp3
4 | 156901015 | emp4
5 | 156901009 | emp5
6 | 156901038 | emp6
问题是每当他们从该应用程序填写表格时,一些 table 不会存储员工的 ID,而是存储来自增量 ID 的新 ID。
例如electronic_parts
table。它们具有如下属性:
| id | electronic_part_name | kind_of_electronic_part_id |
如果 emp1
从网络应用程序填写表格,table 的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | switch | 1 |
如果 emp2
从网络应用程序填写表格,table 的内容如下所示。
| id | electronic_part_name | kind_of_electronic_part_id |
| 1 | duct tape | 10 |
当我尝试将 table 的内容合并到数据中心时,它会崩溃,因为重复的 ID。
当我想到其他 table 中的外键时,情况变得更糟了。例如 customer_order
table.
customer_order
列的 table 如下所示(只是示例,不是实际的 table,但类似)。
|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 |
有谁知道如何解决这个问题?或者有人 suggest/recommend 可以给我一些解决这个问题的好方法吗?
注意:每个员工都有自己的应用程序数据库,所以数据库不是集中的,它是一个独立的数据库,这意味着,我必须将数据库安装到员工的电脑上一个
那个 id
是否在任何其他 table 中使用过?它可能会涉及JOIN
。如果是这样,你在解开 id 时遇到了很大的问题。
如果 id
未在其他任何地方使用,则这些值无关紧要,可以对行重新编号。这将通过将来自不同来源的数据加载到相同的 table 来完成(粗略地说),但是 不 在加载中包含 id
。
或者,如果还有其他列(或列的组合)是 UNIQUE
,则将 that 设为 PRIMARY KEY
并删除id
.
哪种情况适用?我们可以更详细地追究。请为任何相关的 table(s) 提供 SHOW CREATE TABLE
。
在我的第一个案例中(id 在其他地方用作 FK),做这样的事情:
在使用 id
将行插入 table 时,将值增加足够多以避免与现有 ID 冲突。然后做(在同一笔交易中):
UPDATE the_other_table SET fk_id = fk_id + same_increment.
根据需要互相重复 table 和每个 ID。
我认为你的问题出在你的数据库...你没有设计好它。 这是一个 bug 如果你有两个不同用户的 id 。
如果您刚刚在您的数据库中创建了您的 ID 字段唯一,那么两个员工将不会有相同的 ID,所以您的问题出在您的 table 设计中。
只需像这样启动您的 id 字段,您的问题就会得到解决。
CREATE TABLE [YOUR TABLE NAME](
[ID] int NOT NULL IDENTITY(1,1) PRIMARY KEY,
....
这是一个非常规的情况,你可以有一个非常规的解决方案。
我可以建议你两种方法来解决这个问题。
不是对主键使用自动增量,而是生成一个 UUID 并将其用作主键。关于重复概率 在随机 UUID 中:仅在每秒生成 10 亿个 UUID 之后 未来 100 年
在 CodeIgniter 中,您可以使用以下代码片段执行此操作。
$this->db->set('id', 'UUID', FALSE);
这会生成一个 36 个字符的十六进制密钥(带有 4 个破折号 包括)。
ac689561-f7c9-4f7e-be94-33c6c0fb0672
如您所见,字符串中有破折号,使用 CodeIgniter DB 函数将用破折号将其插入数据库中,它仍然 将工作。如果它看起来不干净,您可以删除并 将字符串转换为 32 个字符的键。
您可以在[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
解决这种情况的另一种非常规方法是 添加功能以记录所有已处理的插入、更新、删除查询 在站点中到本地文件。通过这种方式,在每个地方 实施将生成一个包含实际列表的日志文件 随着时间的推移以正确的顺序修改数据库的查询。
在任何时间点,数据库的状态都是 直到那个日期,所有这些查询都发生在过去。
因此,每 5 个月,当您准备好从 员工的个人电脑,而不是采取数据转储,采取这个 包含所有查询日志的文件。(注意:这样的查询日志不会有 自动递增 id,因为它只会在实时创建 它是针对数据库执行的。 )
使用此类文件将数据导入您的数据中心。这不会 冲突,因为它会在您的数据中心生成自动增量 即时的。 (希望您不必 link 本地到数据中心 在未来的任何时间)
id必须是整数吗?如果不是,您可以在 id 上使用前缀,这样每个员工的输入通常都是唯一的。这意味着您必须放弃自动递增,只依靠 table 数据(假设您没有删除任何记录。)
您可能需要在 PHP 中编写代码来处理此问题。如果其他 table 已经在基于 unique/primary 键之后,那就没问题了。
导入后也可以。 像这样 Find duplicates in the same table in MySQL