【问题标题】:Can there be constraints with the same name in a DB?数据库中可以存在同名的约束吗?
【发布时间】:2010-11-26 17:28:50
【问题描述】:

这是我问过here 的后续问题。

数据库中的约束可以同名吗?

说我有:

CREATE TABLE Employer
(
    EmployerCode    VARCHAR(20)    PRIMARY KEY,
    Address         VARCHAR(100)   NULL
)


CREATE TABLE Employee
(
    EmployeeID      INT            PRIMARY KEY,
    EmployerCode    VARCHAR(20)    NOT NULL,
    CONSTRAINT employer_code_fk FOREIGN KEY (EmployerCode) REFERENCES Employer
)


CREATE TABLE BankAccount
(
    BankAccountID   INT            PRIMARY KEY,
    EmployerCode    VARCHAR(20)    NOT NULL,
    Amount          MONEY          NOT NULL,
    CONSTRAINT employer_code_fk FOREIGN KEY (EmployerCode) REFERENCES Employer
)

这是允许的吗?它是否依赖于 DBMS(我在 SQL Server 2005 上)?如果不允许,是否有人对如何解决它有任何建议?

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql constraints


    【解决方案1】:

    这取决于 DBMS。

    例如在PostgreSQL上,答案是yes

    因为 PostgreSQL 不要求约束名称是唯一的 在一个模式中(但仅限于每个表),可能存在 指定的约束名称匹配多个。

    来源:https://www.postgresql.org/docs/current/static/sql-set-constraints.html

    我已经看到外键约束名称在同一架构中的 2 个不同表上相等。

    【讨论】:

      【解决方案2】:

      它是否依赖于 DBMS(我使用的是 SQL Server 2005)?

      是的,显然它确实取决于 DBMS。

      其他答案说这是不允许的,但我有一个 MS SQL CE(“精简版”)数据库,我不小心成功地在两个表中创建了两个 FK 约束,具有相同的约束名称。

      【讨论】:

        【解决方案3】:

        其他答案都很好,但我想我会在标题中添加一个问题的答案,即“数据库中是否存在同名约束?” p>

        MS SQL Server 的答案是肯定的——但前提是约束位于不同的架构中。约束名称必须在架构中是唯一的

        【讨论】:

        • 外键属于什么模式? FK 约束可以引用多个模式中的表...我假设它是声明约束的表的模式,但这总是正确的吗?
        • 这是真的。 EF Core 刚刚为两个表创建了PK_Foo,我想知道这是怎么回事。我意识到这两个表属于不同的模式(dboarc)。我认为这应该是公认的答案。
        【解决方案4】:

        否 - 约束也是一个数据库对象,因此它的名称必须是唯一的。

        尝试添加例如约束的表名,这样它将是唯一的。

        CREATE TABLE BankAccount
        (
            BankAccountID   INT            PRIMARY KEY,
            EmployerCode    VARCHAR(20)    NOT NULL,
            Amount          MONEY          NOT NULL,
            CONSTRAINT FK_BankAccount_Employer 
                FOREIGN KEY (EmployerCode) REFERENCES Employer
        )
        

        我们基本上使用“FK_”(子表)_(父表)“来命名约束,并且对这种命名约定非常满意。

        来自 MSDN 的信息

        约束名称对于模式必须是唯一的(即,同一数据库中的两个不同模式都可以包含具有相同名称的约束)没有明确记录。相反,您需要假设数据库对象的标识符在包含模式中必须是唯一的除非另有说明。所以约束名称是defined 为:

        是约束的名称。约束名称必须遵循标识符规则,但名称不能以数字符号 (#) 开头。如果未提供约束名称,则系统生成的名称将分配给约束。

        将此与index 的名称进行比较:

        是索引的名称。索引名称在表或视图中必须是唯一的,但在数据库中不必是唯一的。索引名称必须遵循标识符的规则。

        显式缩小了标识符的范围。

        【讨论】:

        • +1:我们使用构成表名的单词的首字母作为前缀。
        • 这只是部分正确,因为必须在模式级别而不是数据库级别强制唯一性。见this answer below
        【解决方案5】:

        良好的做法是创建索引和约束名称,并在开头指定表名。 有两种方法,索引/约束类型在开头或结尾)例如。

        UQ_TableName_FieldName
        

        TableName_FieldName_UQ
        

        外键名称还应包含引用的表/字段的名称。

        一个好的命名约定是以 FullName_3LetterUniqueAlias 的形式给出表名,例如。

        Employers_EMR
        Employees_EMP
        BankAccounts_BNA
        Banks_BNK
        

        这使您有机会在查询中使用“预定义”别名,从而提高可读性并简化外键命名,例如:

        EMPEMR_EmployerCode_FK
        BNKEMR_EmployerCode_FK
        

        【讨论】:

          【解决方案6】:

          我一直很困惑为什么约束名称在数据库中必须是唯一的,因为它们似乎与表相关联。

          然后我阅读了 SQL-99 的 ASSERTION 约束,它类似于检查约束,但存在于任何单个表之外。断言中声明的条件必须像任何其他约束一样始终得到满足,但断言可以引用多个表。

          AFAIK 没有 SQL 供应商实现 ASSERTION 约束。但这有助于解释为什么约束名称在范围内是数据库范围的。

          【讨论】:

          • 好吧,即使没有实现断言约束:你真的想要三个同名的外键约束吗?如果您收到说明 FK 名称的 FK 违规错误 - 您如何知道这三个中的哪一个?我认为强制执行唯一约束名称是“好事(tm)”:-)
          • 是的,当然。我的意思是“这种方式在 ANSI SQL 标准中”,但您的观点更加实用。
          • @marc_s 如果约束名称是表范围的,则错误消息也将包含表名称。例如,Postgres 就是这样做的。
          • @marc_s 理想情况下,我希望错误告诉我什么表。虽然,如果必须的话,大约 99% 或更多的时间我可能很容易自己弄清楚。
          • 另外,要求表名会占用键名中的大量空间(最大允许长度为 64),当表名很长时会很痛苦。
          猜你喜欢
          • 2021-09-04
          • 2011-03-11
          • 1970-01-01
          • 2021-11-03
          • 2013-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多