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)));