如何防止 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_partstable。它们具有如下属性:

| 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,
....

这是一个非常规的情况,你可以有一个非常规的解决方案。

我可以建议你两种方法来解决这个问题。

  1. 不是对主键使用自动增量,而是生成一个 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
    
  2. 解决这种情况的另一种非常规方法是 添加功能以记录所有已处理的插入、更新、删除查询 在站点中到本地文件。通过这种方式,在每个地方 实施将生成一个包含实际列表的日志文件 随着时间的推移以正确的顺序修改数据库的查询。

    在任何时间点,数据库的状态都是 直到那个日期,所有这些查询都发生在过去。

    因此,每 5 个月,当您准备好从 员工的个人电脑,而不是采取数据转储,采取这个 包含所有查询日志的文件。(注意:这样的查询日志不会有 自动递增 id,因为它只会在实时创建 它是针对数据库执行的。 )

    使用此类文件将数据导入您的数据中心。这不会 冲突,因为它会在您的数据中心生成自动增量 即时的。 (希望您不必 link 本地到数据中心 在未来的任何时间)

    [1]: https://github.com/Repox/codeigniter-uuid

id必须是整数吗?如果不是,您可以在 id 上使用前缀,这样每个员工的输入通常都是唯一的。这意味着您必须放弃自动递增,只依靠 table 数据(假设您没有删除任何记录。)

您可能需要在 PHP 中编写代码来处理此问题。如果其他 table 已经在基于 unique/primary 键之后,那就没问题了。

导入后也可以。 像这样 Find duplicates in the same table in MySQL