course_code的适当数据类型是什么?

时间:2012-05-02 11:14:51

标签: mysql sql

好的,我被要求准备一个大学数据库,我需要以某种方式存储某些数据。 例如,我需要存储一个包含字母后跟两个整数的课程代码。例如。 I45,D61等。 所以它应该是VARCHAR(3)我是对的吗?但我仍然不确定这是否是正确的道路。我也不确定我将如何在SQL脚本中强制执行此操作。 我似乎无法在笔记中找到任何答案,而且我正在编写这个问题的数据字典,然后我才会插入脚本。

任何提示?

3 个答案:

答案 0 :(得分:4)

尽可能使主键没有商业意义。您可以轻松更改数据库设计,而不会对应用程序层产生严重影响。使用哑主键时,用户不会将意义与特定记录的标识符相关联。

您所询问的内容被称为智能密钥,通常是用户可见的。非用户可见键称为哑或代理键,有时这个非用户可见键变得可见,但这不是问题,因为用户不会解释大多数哑键。例如,您想要更改此问题的标题,此问题的ID将保持不变https://stackoverflow.com/questions/10412621/

使用智能主键,有时出于审美原因,用户希望指定密钥应如何格式化和外观。这可以经常像用户那样经常更新。这将是应用程序方面的问题,因为这需要在相关表上级联更改;和数据库方面一样,因为相关表上的密钥的级联更新非常耗时

在此处阅读详细信息:

http://www.bcarter.com/intsurr1.htm


代理键的优点:http://en.wikipedia.org/wiki/Surrogate_key

您可以在代理键(也称为哑键)旁边实现自然键(也称为智能键)

-- Postgresql has text type, it's a character type that doesn't need length, 
-- it can be upto 1 GB
-- On Sql Server use varchar(max), this is upto 2 GB

create table course
(
    course_id serial primary key, -- surrogate key, aka dumb key

    course_code text unique, -- natural key. what's seen by users e.g. 'D61'

    course_name text unique, -- e.g. 'Database Structure'
    date_offered date
);

这种方法的优点是,当未来学校扩展时,他们决定提供西班牙语语言数据库结构,您的数据库与用户引入的用户解释值隔离。< / p>

假设您的数据库使用智能密钥启动:

create table course
(
    course_code primary key, -- natural key. what's seen by users e.g. 'D61'

    course_name text unique, -- e.g. 'Database Structure'
    date_offered date
);

接下来是西班牙语语言数据库结构课程。如果用户将自己的规则引入您的系统,他们可能会在course_code值上输入: D61 / ESP ,其他人会选择 ESP-D61 ESP:D61 。如果用户决定他们自己的主键规则,事情就会失控,然后他们会告诉你根据他们在主键格式上创建的任意规则查询数据,例如: “列出我们在这所学校提供的所有西班牙语课程”,史诗要求不是吗?那么一个好的开发人员会做些什么来适应数据库设计的变化呢?他/她将正式化数据结构,将重新设计表格:

create table course
(
    course_code text, -- primary key
    course_language text, -- primary key

    course_name text unique,
    date_offered date,

    constraint pk_course primary key(course_code, course_language)
);

你看到了问题吗?这将导致停机时间,因为您需要将更改传播到依赖于该课程表的表的外键。当然,您还需要先调整这些依赖表。看看它不仅可能导致DBA,也可能导致开发人员的麻烦。

如果您从一开始就使用dumb主键开始,即使用户在您不知情的情况下向系统引入规则,也不会导致任何大量数据更改或数据架构更改到您的数据库设计。这可以让你花时间相应地调整你的申请。如果您将智能放在主键中,那么上面的用户需求可以使您的主键自然地转移到复合主键。这不仅对数据库设计重组和数据的大规模更新很困难,您也很难快速调整应用程序以适应新的数据库设计。

create table course
(
    course_id serial primary key,
    course_code text unique, -- natural key. what's seen by users e.g. 'D61'
    course_name text unique, -- e.g. 'Database Structure'
    date_offered date
);

因此,使用代理键,即使用户将新规则或信息存储到course_code,您也可以安全地对表格进行更改,而不会迫使您快速使您的应用程序适应新设计。您的应用程序仍可继续运行,无需停机。它可以让你有时间相应地调整你的应用程序。这将是语言特定课程的变化:

create table course
(
    course_id serial primary key,

    course_code text, -- natural key. what's seen by users e.g. 'D61'
    course_language text, -- natural key. what's seen by users e.g. 'SPANISH'

    course_name text unique, -- e.g. 'Database Structure in Spanish'
    date_offered date,

    constraint uk_course unique key(course_code, course_language)
);

正如您所看到的,您仍然可以执行大量UPDATE语句,将用户强加的course_code规则拆分为两个字段,这些字段不需要对依赖表进行更改。如果使用智能复合主键,则重构数据将迫使您将复合主键上的更改级联到从属表的复合外键。使用哑主键,您的应用程序仍然可以照常运行,您可以随时根据新设计(例如新文本框,课程语言)修改应用程序的更改。使用哑主键,从属表不需要复合外键指向课程表,他们仍然可以使用相同的旧哑/代理主键

使用哑主键时,主键和外键的大小不会扩展

答案 1 :(得分:2)

这是域名解决方案。仍然不完美,检查可以改善等。

set search_path='tmp';

DROP DOMAIN coursename CASCADE;
CREATE DOMAIN coursename AS varchar NOT NULL
    CHECK (length(value) > 0
    AND  SUBSTR(value,1) >= 'A' AND SUBSTR(value,1) <= 'Z'
    AND  SUBSTR(value,2) >= '0' AND SUBSTR(value,2) <= '9' )
    ;

DROP TABLE course CASCADE;
CREATE TABLE course
    ( cname coursename PRIMARY KEY
    , ztext varchar
    , UNIQUE (ztext)
    );
INSERT INTO course(cname,ztext) 
  VALUES ('A11', 'A 11' ), ('B12', 'B 12' ); -- Ok
INSERT INTO course(cname,ztext)
  VALUES ('3','Three' ), ('198', 'Butter' ); -- Will fail
BTW:对于“实际”PK,我可能会使用代理ID。但上面的域(使用UNIQUE约束)可以作为“逻辑”候选键。

这基本上是表是域范例的结果。

答案 2 :(得分:1)

我强烈建议您不要对数据类型过于具体,因此VARCHAR(8)之类的内容会没问题。原因是:

  • 明年代码中可能会有四个字符。业务需求一直在变化,因此不要过多地锁定字段长度
  • 让应用程序层处理验证 - 毕竟,它必须将验证问题传达给用户
  • 通过将其限制为3个字符来增加很少或没有商业价值
  • 使用mysql,虽然你可以在列上定义 check约束(希望“验证”这些值),但是它们会被忽略并且仅出于兼容性原因而被允许

在系统的所有组件中,数据库架构始终是最难改变的,因此在数据类型中允许一些灵活性以尽可能避免更改。