SQL疑惑解疑

+----------------------------------------------------------------------------------------+
SQL的疑惑:
+----------------------------------------------------------------------------------------+
需要学会如何在数据库而不是在代码中指定的内容

mysql> CREATE TABLE FircalYears(
    -> fiscal_year INTEGER,
    -> start_date DATE,
    -> end_date DATE
    -> );
他存储的日期范围决定某个给定日期属于哪一个财政年度.例如,美国联邦政府的财政年度是从10月1日到次年9月底.用来查询这个表的标量子查询是:
(SELECT F1.fiscal_year
FROM FiscalYears AS F1
WHERE outside_date BETWEEN F1.start_date AND F1.end_date)

他存储的日期范围是决定某个给定日期属于哪一个财政年度.例如,美国联邦政府的财政年度是从10月1日到次年9月底.用来查询这个表的标量子查询:
(SELECT F1.fiscal_year
    FROM FiscalYears AS F1
    WHERE outside_date BETWEEN F1.start_date AND F1.end_date);
你的任务是添加所有能想到的约束,以确保表中只包含正确的信息.
数据库供应商们都有各种不同的日期和时间函数,但假定这里只使用SQL-92的时间运算以及EXTRACT([YEAR|MONTH|DAY] FROM <日期表达式>函数,这个函数返回一个代表日期端中某个字段的整数/

解惑:
1.使所有的列都成为NOT NULL,因为没有理由允许他们为NULL.
2.很多SQL程序员立即想到添加PRIMARY KEY,因为财政年度实际上是一对日期(start_date,end_date)的另一个叫法,所以你可以添加约束PRIMARY KEY(fiscal_year,start_date,end_date).这还不够
还会出现
    (1995,'1994-10-01','1995-09-30')
    (1996,'1995-10-01','1996-08-30')    <==错误
    (1997,'1996-10-01','1997-09-30')
    (1998,'1997-10-01','1998-09-30')
因为不希望出现任何重复日期,可以采取类似的方法,通过添加约束UNIQUE(fiscal_year),UNIQUE(start_date),来继续修复一些问题.

还有一个因为过于明显而几乎被每个人都忘掉的约束是:
CHECK(start_date < end_date)或者是CHECK(start_date <= end_date),根据情况选用.

一个更好的方法是像前面一样使用约束PRIMARY KEY(fiscal_year),但是因为每年的开始日期和结束日期都相同,所以可以在这些列的声明中使用约束.

CREATE TABLE FiscalYears(
    fiscal_year  INTEGER NOT NULL PRIMARY KEY,
    start_date   DATE NOT NULL,
    CONSTRAINT valid_start_date
    CHECK((EXTRACT (YEAR FROM start_date) = fiscal_year -1)
    AND (EXTRACT (MONTH FROM start_date)=10)
    AND (EXTRACT (DAY FROM start_date) = 01),
end_date DATE NOT NULL,
CONSTRAINT valid_end_date
    CHECK((EXTRACT (YEAR FROM end_date)=fiscal_year)
        AND (EXTRACT (MONTH FROM end_date)=09)
        AND (EXTRACT (DAY FROM end_date)=30)));

posted @ 2012-09-22 18:46  sgsheg  阅读(157)  评论(0编辑  收藏  举报