MySQL:使用不同的模式

时间:2018-02-03 03:30:16

标签: mysql sql database

我有一张设计糟糕的桌子:

CREATE TABLE token (
    id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    user_id INT(10) UNSIGNED NOT NULL,

    token VARCHAR(191) NOT NULL,
    expiration TIMESTAMP NOT NULL,

    created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
    deleted_at TIMESTAMP NULL DEFAULT NULL,

    PRIMARY KEY (id),
    FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE
);

我之前认为它现在很糟糕的原因是因为现在我不能重用那个token表,如果我想要一个与电子邮件或其他相关的令牌。我可以添加email_id列,但是我需要丑陋的逻辑来确定令牌是分别用于用户还是电子邮件。

我希望对此设计进行规范化,以便我可以将一个token表与任何user_idemail_id相关联,并user_token和关系的email_token数据透视表。

但我也在使用迁移,因此我无法重写我的架构。我需要使用数据库中的数据动态修改它。

我需要做以下事情:

  1. 制作新的user_tokenemail_token(完整版)
  2. token.id复制到user_token.token_id列,并将token.user_id值复制到user_token.user_id列。复制需要在INSERT语句中完成,因为user_token表格是全新的,没有数据(TODO)
  3. 删除token.user_id(完成)
  4. 第2步是我需要帮助的部分。写这个查询会有任何帮助。

    如果新架构有助于为第2步创建查询,那么这就是新架构:

    CREATE TABLE token (
        id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    
        token VARCHAR(191) NOT NULL,
        expiration TIMESTAMP NOT NULL,
    
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
        deleted_at TIMESTAMP NULL DEFAULT NULL,
    
        PRIMARY KEY (id)
    );
    
    CREATE TABLE user_token (
        id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        user_id INT(10) UNSIGNED NOT NULL,
        token_id INT(10) UNSIGNED NOT NULL,
    
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
        deleted_at TIMESTAMP NULL DEFAULT NULL,
    
        PRIMARY KEY (id),
        FOREIGN KEY (user_id) REFERENCES user (id) ON DELETE CASCADE,
        FOREIGN KEY (token_id) REFERENCES token (id) ON DELETE CASCADE
    );
    
    CREATE TABLE email_token (
        id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        email_id INT(10) UNSIGNED NOT NULL,
        token_id INT(10) UNSIGNED NOT NULL,
    
        created_at TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
        deleted_at TIMESTAMP NULL DEFAULT NULL,
    
        PRIMARY KEY (id),
        FOREIGN KEY (email_id) REFERENCES user (id) ON DELETE CASCADE,
        FOREIGN KEY (token_id) REFERENCES token (id) ON DELETE CASCADE
    );
    

1 个答案:

答案 0 :(得分:1)

如果您没有从令牌表中删除token.user_id和token.email_id列,则可以使用简单的INSERT复制它们:

INSERT INTO user_token (user_id, token_id)
SELECT user_id, id
FROM token

INSERT INTO email_token (email_id, token_id)
SELECT email_id, id
FROM token

如果你想复制created_at,updated_at和deleted_at列,你可以将它们添加到查询中:

INSERT INTO user_token (user_id, token_id, created_at, updated_at, deleted_at)
SELECT user_id, id, created_at, updated_at, deleted_at
FROM token

INSERT INTO email_token (email_id, token_id, created_at, updated_at, deleted_at)
SELECT email_id, id, created_at, updated_at, deleted_at
FROM token

这会将它们复制到新表中。然后,您只需要通过简单的ALTER:

从令牌表中删除user_id和email_id列

首先删除外键:

ALTER TABLE token DROP FOREIGN KEY user_id

然后删除栏目:

ALTER TABLE token DROP COLUMN user_id;
ALTER TABLE token DROP COLUMN email_id;