【问题标题】:How to alter existing foreign key to add a constraint name如何更改现有外键以添加约束名称
【发布时间】:2018-05-13 13:38:03
【问题描述】:

我之前写过我的create 查询如下,其中外键未命名。

CREATE TABLE My_Table_Name (
    USER_ID VARCHAR(255) NOT NULL,
    CONSENT_ID VARCHAR(255)  NOT NULL,
    PRIMARY KEY (USER_ID, CONSENT_ID),
    FOREIGN KEY (CONSENT_ID) REFERENCES ANOTHER_TABLE_NAME (CONSENT_ID) ON DELETE CASCADE
);

现在表中有数据,我想将约束名称添加到现有外键。我怎样才能做到这一点?

PS:我需要的是ALTER查询

另外,如果数据库是 SQL Server 而不是 MySQL,查询会有所不同吗?

【问题讨论】:

  • 请注意,FK 不是未命名的。使用SHOW CREATE TABLE My_Table_Name 查看 MySQL 选择的名称。你可能没问题。您还将看到已创建一个新索引来支持 FK。

标签: mysql sql sql-server


【解决方案1】:

MySQL 中的外键约束一旦创建就不能重命名。您必须删除约束,然后使用您想要的名称重新创建它。

首先你必须去挖掘外键约束名称(有一个,你只是不知道它是什么):

SELECT constraint_name
FROM information_schema.REFERENTIAL_CONSTRAINTS
WHERE constraint_schema = 'your_db_name' AND table_name = 'My_Table_Name';

现在重命名约束:

ALTER TABLE My_Table_Name
DROP FOREIGN KEY some_foreign_key    -- from above query
ADD CONSTRAINT fk_my_constraint FOREIGN KEY (CONSENT_ID)
    REFERENCES ANOTHER_TABLE_NAME (CONSENT_ID) ON DELETE CASCADE;

【讨论】:

  • 我相信SET @@FOREIGN_KEY_CHECKS = 0; 在运行此查询之前会使其运行得更快,因为服务器不会尝试验证是否违反了约束,这是不应该的。禁用外键检查还应该允许您在语句末尾使用 ALTER TABLE ..., ALGORITHM=INPLACE, LOCK=NONE 以实现快速的就地 DDL。 SET @@FOREIGN_KEY_CHECKS=1; 或完成后断开连接。
【解决方案2】:

您使用constraint 关键字:

CREATE TABLE My_Table_Name (
  USER_ID VARCHAR(255) NOT NULL,
  CONSENT_ID VARCHAR(255)  NOT NULL,
  CONSTRAINT pk_mY_table_name PRIMARY KEY (USER_ID, CONSENT_ID),
  CONSTRAINT fk_my_table_name_consent_id FOREIGN KEY (CONSENT_ID) REFERENCES ANOTHER_TABLE_NAME (CONSENT_ID) ON DELETE CASCADE
);

这是标准语法,几乎在任何数据库中都是相同的。

在这两个数据库中,您都需要通过元数据表来获取现有约束的名称。然后添加一个新的:

alter table my_table_name
    drop constraint x,
    drop constraint y;

alter table my_table_name
    CONSTRAINT pk_mY_table_name PRIMARY KEY (USER_ID, CONSENT_ID),
    CONSTRAINT fk_my_table_name_consent_id FOREIGN KEY (CONSENT_ID) REFERENCES ANOTHER_TABLE_NAME (CONSENT_ID) ON DELETE CASCADE;

您可以从INFORMATION_SCHEMA.TABLE_CONSTRAINTS 获取约束名称(请参阅here)。这在两个数据库中都可用。我要注意INFORMATION_SCHEMA 表中的列有时会有所不同。

【讨论】:

  • 我需要一个 alter 查询来更改现有表,如果我的问题不清楚,请见谅。
【解决方案3】:

在 MS SQL 中,匿名约束将获得系统生成的名称。

您可以使用以下查询来获取生成的约束名称:

SELECT
    FK.CONSTRAINT_NAME
FROM
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
    INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON
        PK.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND
        PK.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND
        PK.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME
    INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON
        FK.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND
        FK.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND
        FK.CONSTRAINT_NAME = RC.CONSTRAINT_NAME
WHERE
    FK.TABLE_NAME = N'My_Table_Name' AND
    PK.TABLE_NAME = N'ANOTHER_TABLE_NAME'

这会给出类似“FK__My_Table___CONSE__5535A963”的结果。

接下来,您可以使用sp_rename 存储过程,如下所示:

EXECUTE sp_rename N'FK__My_Table___CONSE__5535A963', N'FK_MyRenamedConstraint';

当然,您需要在查询中使用正确的约束名称。

(您可以忽略 SQL Server 的默认警告,即重命名可能会破坏现有脚本和存储过程。)

当再次执行第一个查询时,它会显示新名称。

我不知道这一切应该如何在 MySQL 中完成...抱歉...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-18
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多