在列中构建并显示复杂的复合主键

时间:2009-05-08 10:58:29

标签: sql sql-server

我需要构建一个由3个部分组成的主键。

  • 第一部分长3个字母 并且必须是a后跟两个 数字例如“a00”
  • 第二部分是3位数 唯一标识符包括领先 ZEROES,例如“003”
  • 第三部分是年份部分 日期,例如“2008”

这一切都用破折号分开,所以完整的密钥看起来像“a00-014-2008”

我的解决方案是保存三个单独的列,每个列都包含未格式化的数据,然后添加聚簇主键约束并在需要在视图中显示时对其进行格式化。这是一个很好的方式吗?我认为可能有一种方法可以使用触发器使整个密钥更新,但我不知道如何。我如何连接并在视图中显示它?

虽然不是一个家庭作业问题,但这对我的学业有帮助。

3 个答案:

答案 0 :(得分:5)

我的问题是:这三个价值中的任何一个都有自己的含义吗?或者它们只是主键的组成部分?如果他们完全没有其他意义那么你最好只创建一个具有整个价值的单一栏目。

现在“意义”可能很难获得资格。这可能意味着它是一个特定的客户代码或搜索到的东西,或者很多东西。

通常我会尝试避免使用复合键,因为它们会使连接变得复杂,并且通常会使ORM(通常将此类练习视为正确或错误 - 视为“遗留”)使您的生活变得困难。

如果这些字段确实有意义,那么可以说它们不应该是主键的一部分。我将这种做法视为mistake。我几乎总是使用自动编号列或序列作为主键值(称为“技术键”而不是语义键)。

鉴于用户提供了部分内容并且需要以特定方式进行格式化,我假设密钥具有整体意义,无论是产品代码,患者代码,预订号还是类似的东西。这是对的吗?

如果是这样的话,鉴于我和我几乎完全偏爱技术密钥(意见因此问题而异),我认为不会将其作为主键。为此创建一个自动编号字段。只需将其作为具有varchar(12)或其他任何索引的唯一索引的列。

答案 1 :(得分:3)

CREATE TABLE mytable (
      first TINYINT NOT NULL CHECK(first BETWEEN 0 AND 99),
      second INT NOT NULL CHECK (second BETWEEN 0 AND 999),
      third INT NOT NULL,
      CONSTRAINT pk_mytable_123 PRIMARY KEY (first, second, third)
      )
GO
CREATE VIEW v_mytable AS
SELECT  'a' + RIGHT('00' + CAST(first AS VARCHAR), 2) AS first,
        RIGHT('0000' + CAST(second AS VARCHAR), 4) AS second,
        third
FROM    mytable
GO

INSERT
INTO    mytable
VALUES  (1, 1, 2008)
GO

SELECT  *
FROM    v_mytable
GO

first  second  third
----   ----    ----
a01    0001    2008

此主键仅包含INT个值,所有格式都将在视图中完成。

请注意,为了在性能方面获得最佳结果,您最好创建计算列而不是视图,并在这些列中创建额外的UNIQUE索引:

CREATE TABLE mytable (
      _first TINYINT NOT NULL CHECK(_first BETWEEN 0 AND 99),
      _second INT NOT NULL CHECK (_second BETWEEN 0 AND 999),
      third INT NOT NULL,
      first AS 'a' + RIGHT('00' + CAST(_first AS VARCHAR), 2),
      second AS RIGHT('0000' + CAST(_second AS VARCHAR), 4)
      CONSTRAINT pk_mytable_123 PRIMARY KEY (_first, _second, third)
      )

CREATE UNIQUE INDEX ux_mytable_123 ON mytable (first, second, third)

答案 2 :(得分:0)

主键传统上有两个用途:唯一标识一行,并允许其他数据库表引用它。复合主键实现了第一个目的,但是使第二个目标很难,因为另一个表必须引用3列。 ORM系统也是如此,甚至是网页的更新。

最佳实践解决方案是将标识列作为主键。这允许轻松引用行,并且是所有ORM层可以处理的场景。然后在构成主键的三列上添加“唯一”索引。这样你就可以拥有两全其美。