• SQL puzzles and answers读书笔记——财年表


    最近开始阅读数据库大师Joe Celko的《SQL PUZZLES AND ANSWERS》一书。这本书每篇都是一个SQL谜题,涉及数据库设计、开发。我看的是英文第二版,在这里做个读书笔记,顺便用T-SQL和PL/SQL来实现其中的代码。

    谜题1——财年表

    我们首先来创建一张表(以下代码在SQL Server 2008和Oracle上都能运行通过):

    create table FiscalYearTable1
    (
    	fiscal_year int,
    	start_date date,
    	end_date date
    );

    这张表存储了每个财年的起始日期和结束日期。用以下查询能找出outside_date所属的财年:

    select
    	F1.fiscal_year
    from
    	FiscalYearTable1 as F1
    where
    	outside_date between F1.start_date and F1.end_date

    我们的谜题是:对于这张表加哪些约束能防止错误数据的输入?

    讨论与方案

    1. 首先能想到的是给每个列加上NOT NULL约束,因为在这张表中存放NULL值没有特别的意义和好处。

    2. 作为SQL程序员很快能想到要加PRIMARY KEY约束。对于FiscalYearTable1表可以在fiscal_year列加PRIMARY KEY约束。同样start_date和end_date列也不允许重复值的出现,所以可以加上UNIQUE约束。

    3. 约束CHECK(start_date < end_date)非常明显,但却容易被人遗忘。

    4. 虽然有了上述约束,但还是无法避免如下的错误:

    (2007, ‘2006-10-01’, '2007-09-30')

    (2008, ‘2007-10-01’, '2008-09-30’)

    (2009, ‘2008-10-01’, '2009-08-30’) <==出错了!

    (2010, ‘2009-10-01’, '2010-09-30’)

    对于如上start_date月日和end_date月日固定的财年表,可以加更为精确的约束。代码如下:

    T-SQL:

    create table FiscalYearTable1
    (
    	fiscal_year int not null primary key,
    	start_date date not null,
    	constraint valid_start_date
    		check((year(start_date) = fiscal_year - 1)
    				and (month(start_date) = 10)
    				and (day(start_date) = 1)),
    	end_date date not null,
    	constraint valid_end_date
    		check((year(end_date) = fiscal_year)
    				and (month(end_date) = 9)
    				and (day(end_date) = 30))
    );

    PL/SQL:

    create table FiscalYearTable1
    (
      fiscal_year int 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) = 1)),
      end_date date not null,
      constraint valid_end_date
        check((extract(year from end_date) = fiscal_year)
              and (extract(month from end_date) = 9)
              and (extract(day from end_date) = 30))
    );

    5. 有些公司的财年计算方式和4中的不同,如以52周为一个财年。这种情况下就无法使用4中对start_date和end_date的约束了,我们可以加如下约束(52周 × 7天 = 364天):

    CHECK((end_date – start_date) = INTERVAL 364 DAYS)

  • 相关阅读:
    宏中的逗号
    DES算法
    [microsoft]PE和COFF文件格式
    [流媒体]VLC主要模块
    [转][C/C++]函数名字修饰(Decorated Name)方式
    [VS]vs的宏
    [windows操作系统]system32下的那些好东西
    [微软]technet与msdn
    [windows驱动]标准驱动例程
    [windows操作系统]内核性能剖析
  • 原文地址:https://www.cnblogs.com/DBFocus/p/1801012.html
Copyright © 2020-2023  润新知