關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)

2018-08-12 22:09 更新

SQL 關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)

什么是關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)?

RDBMS 是關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(Relational DataBase Management System)的縮寫,它是 SQL 以及所有現(xiàn)代數(shù)據(jù)庫(kù)系統(tǒng),例如 MS SQL Server、IBM DB2、Oracle、MySQL 和 MS Access等的基礎(chǔ)。

關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(RDBMS)是一種基于 E.F. 科德提出的關(guān)系模型的數(shù)據(jù)庫(kù)管理系統(tǒng)。

什么是表?

RDBMS 中的數(shù)據(jù)存儲(chǔ)在被稱作的數(shù)據(jù)庫(kù)對(duì)象中。表是相互關(guān)聯(lián)的數(shù)據(jù)記錄的集合,由一系列的行和列組成。

謹(jǐn)記,表是關(guān)系型數(shù)據(jù)庫(kù)中最常見(jiàn)也是最簡(jiǎn)單的數(shù)據(jù)存儲(chǔ)形式。下面是一個(gè)客戶信息表的例子:

    +----+----------+-----+-----------+----------+
    | ID | NAME     | AGE | ADDRESS   | SALARY   |  
    +----+----------+-----+-----------+----------+  
    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |  
    |  2 | Khilan   |  25 | Delhi     |  1500.00 |  
    |  3 | kaushik  |  23 | Kota      |  2000.00 |  
    |  4 | Chaitali |  25 | Mumbai    |  6500.00 |  
    |  5 | Hardik   |  27 | Bhopal    |  8500.00 |  
    |  6 | Komal    |  22 | MP        |  4500.00 |  
    |  7 | Muffy    |  24 | Indore    | 10000.00 |  
    +----+----------+-----+-----------+----------+  

什么是字段?

每張表都能夠劃分成更小的實(shí)體——字段。例如,上面的客戶信息表中有 ID、NAME、AGE、ADDRESS 和 SALARY 五個(gè)字段。

一個(gè)字段限定了數(shù)據(jù)表中的列,被用來(lái)維護(hù)表中所有記錄的特定信息。

什么是記錄或者數(shù)據(jù)行?

記錄或者說(shuō)數(shù)據(jù)是存在于數(shù)據(jù)表中的獨(dú)立條目。例如,上面的客戶信息表中有 7 條記錄。下面是客戶信息表中的一條記錄:

    +----+----------+-----+-----------+----------+  
    |  1 | Ramesh   |  32 | Ahmedabad |  2000.00 |  
    +----+----------+-----+-----------+----------+  

記錄就是表中水平排列的數(shù)據(jù)構(gòu)成的實(shí)體。

什么是列?

是表中豎直排列的實(shí)體,它包含了表中與某一特定字段相關(guān)的所有信息。

例如,上面的客戶信息表中有字段為 ADDRESS 的列,存儲(chǔ)了客戶的地址,其內(nèi)容如下所示:

    +-----------+  
    | ADDRESS   |  
    +-----------+  
    | Ahmedabad |  
    | Delhi     |  
    | Kota      |  
    | Mumbai    |  
    | Bhopal    |  
    | MP        |  
    | Indore    |  
    +----+------+  

什么是 NULL 值?

NULL 值是表中以空白形式出現(xiàn)的值,表示該記錄在此字段處沒(méi)有設(shè)值。

一定要明白 NULL 值同 0 值或者包含空格的字段是不同的。值為 NULL 的字段是在記錄創(chuàng)建的時(shí)候就被留空的字段。

SQL 約束

約束是表中的數(shù)據(jù)列必須遵守的規(guī)則,用于限制表中數(shù)據(jù)的類型。約束保證了數(shù)據(jù)庫(kù)中數(shù)據(jù)的精確性和可靠性。

約束可以限制列或者表。列級(jí)的約束只限制單一的列,而表級(jí)的約束作用于整個(gè)表。

以下是 SQL 中常見(jiàn)的約束:

  • NOT NULL 約束:保證列中數(shù)據(jù)不能有 NULL 值
  • DEFAULT 約束:提供該列數(shù)據(jù)未指定時(shí)所采用的默認(rèn)值
  • UNIQUE 約束:保證列中的所有數(shù)據(jù)各不相同
  • 主鍵:唯一標(biāo)識(shí)數(shù)據(jù)表中的行/記錄
  • 外鍵:唯一標(biāo)識(shí)其他表中的一條行/記錄
  • CHECK 約束:此約束保證列中的所有值滿足某一條件
  • 索引:用于在數(shù)據(jù)庫(kù)中快速創(chuàng)建或檢索數(shù)據(jù)

NOT NULL 約束

默認(rèn)情況下,數(shù)據(jù)表中的字段接受 NULL 值。如果你不想讓某個(gè)字段接受 NULL 值,那么請(qǐng)為該字段定義此約束,以指明該字段不接受 NULL 值。

NULL 并不是指沒(méi)有數(shù)據(jù),而是指該字段數(shù)據(jù)未知

示例:

例如,下述 SQL 語(yǔ)句創(chuàng)建了一個(gè)新的數(shù)據(jù)表 CUSTOMERS,并添加了五個(gè)字段,其中三個(gè)字段——ID、NAME 和 AGE——被指定為 NOT NULL:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

對(duì)于 Oracle 和 MySQL 來(lái)說(shuō),如果 CUSTOMERS 表已經(jīng)存在,此時(shí)再要給 SALARY 字段添加 NOT NULL 約束的話,SQL 語(yǔ)句應(yīng)當(dāng)如下:

    ALTER TABLE CUSTOMERS
       MODIFY SALARY  DECIMAL (18, 2) NOT NULL;

DEFAULT 約束

DEFAULT 約束在 INSERT INTO 語(yǔ)句沒(méi)有提供的情況下,為指定字段設(shè)置默認(rèn)值。

示例:

例如,下述 SQL 語(yǔ)句創(chuàng)建了一個(gè)名為 CUSTOMERS 的新表,并添加了五個(gè)字段。這里,SALARY 字段的默認(rèn)值為 5000。因此,如果 INSERT INTO 沒(méi)有為該字段提供值的話,該字段就為默認(rèn)值 5000。

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2) DEFAULT 5000.00,       
           PRIMARY KEY (ID)
    );

如果 CUSTOMERS 表已經(jīng)存在,此時(shí)再要給 SALARY 字段添加 DEFAULT 約束的話,你需要類似下面的語(yǔ)句:

    ALTER TABLE CUSTOMERS
       MODIFY SALARY  DECIMAL (18, 2) DEFAULT 5000.00;

刪除 DEFAULT 約束:

要?jiǎng)h除 DEFAULT 約束的話,請(qǐng)使用下面的 SQL 語(yǔ)句:

    ALTER TABLE CUSTOMERS
       ALTER COLUMN SALARY DROP DEFAULT;

UNIQUE 約束

UNIQUE 約束使得某一字段對(duì)任意兩條記錄來(lái)說(shuō)都不能相同。例如,在 CUSTOMERS 表中,你或許想讓任何人的年齡(age)都不相同。

示例:

例如,下述 SQL 語(yǔ)句創(chuàng)建了一個(gè)名為 CUSTOMERS 的新表,并添加了五個(gè)字段,其中 AGE 字段被設(shè)為 UNIQUE,于是任意兩條記錄的 AGE 都不同:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL UNIQUE,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

如果 CUSTOMERS 表已經(jīng)存在,再要為 AGE 字段添加 UNIQUE 約束的話,你需要像下面這樣寫 SQL 語(yǔ)句:

    ALTER TABLE CUSTOMERS
       MODIFY AGE INT NOT NULL UNIQUE;

還可以使用如下所示的語(yǔ)法,該語(yǔ)法還支持對(duì)作用于多個(gè)字段的約束進(jìn)行命名:

    ALTER TABLE CUSTOMERS
       ADD CONSTRAINT myUniqueConstraint UNIQUE(AGE, SALARY);

刪除 UNIQUE 約束

要?jiǎng)h除 UNIQUE 約束的話,請(qǐng)使用如下 SQL 語(yǔ)句:

    ALTER TABLE CUSTOMERS
       DROP CONSTRAINT myUniqueConstraint;

如果你在使用 MySQL,那么下面的語(yǔ)法也是可行的:

    ALTER TABLE CUSTOMERS
       DROP INDEX myUniqueConstraint;

主鍵

主鍵是數(shù)據(jù)表中唯一確定一條記錄的字段。主鍵必須包含唯一值,并且不能為 NULL。

每張數(shù)據(jù)表只能有一個(gè)主鍵,不過(guò)一個(gè)主鍵可以包含一個(gè)或者多個(gè)字段。如果主鍵由多個(gè)字段組合而成,這些字段就被稱作組合鍵。

如果一個(gè)字段被定義為了某表的主鍵,則任意兩條記錄在該字段處不能相同。

注意:在創(chuàng)建數(shù)據(jù)表的時(shí)候,需要用到這些概念。

創(chuàng)建主鍵:

如下是將 ID 定義為 CUSTOMERS 表主鍵的語(yǔ)法:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

如果 CUSTOMERS 表已經(jīng)存在了,再要將 ID 定義為主鍵的話,請(qǐng)使用下面的語(yǔ)句:

    ALTER TABLE CUSTOMER ADD PRIMARY KEY (ID);

注意:如果你要使用 ALTER TABLE 語(yǔ)句來(lái)添加主鍵,那么主鍵所在的列必須已經(jīng)被聲明為 NOT NULL 了。

要用多個(gè)字段來(lái)定義主鍵的話,請(qǐng)使用如下 SQL 語(yǔ)法:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),        
           PRIMARY KEY (ID, NAME)
    );

如果 CUSTOMERS 表已經(jīng)存在,此時(shí)再要將 ID 和 NAMES 字段定義為主鍵的話,請(qǐng)使用如下 SQL 語(yǔ)法:

    ALTER TABLE CUSTOMERS 
       ADD CONSTRAINT PK_CUSTID PRIMARY KEY (ID, NAME);

刪除主鍵

你可以將主鍵約束從數(shù)據(jù)表中刪除,語(yǔ)法如下:

    ALTER TABLE CUSTOMERS DROP PRIMARY KEY ;

外鍵

外鍵用于將兩個(gè)數(shù)據(jù)表連接在一起,有時(shí)候也被稱作“參照鍵”。

外鍵為單一字段或者多個(gè)字段的組合,并與另外一個(gè)數(shù)據(jù)表的主鍵相匹配。

兩個(gè)表之間的關(guān)系是:一個(gè)表的主鍵與另一個(gè)表的外鍵相匹配。

示例:

考慮如下兩個(gè)表的結(jié)構(gòu):

CUSTOMERS 表:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

ORDERS 表:

    CREATE TABLE ORDERS (
           ID          INT        NOT NULL,
           DATE        DATETIME, 
           CUSTOMER_ID INT references CUSTOMERS(ID),
           AMOUNT     double,
           PRIMARY KEY (ID)
    );

如果 ORDERS 表已經(jīng)存在,并且沒(méi)有設(shè)置外鍵,那么可以使用下面的語(yǔ)法來(lái)修改數(shù)據(jù)表以指定外鍵。

    ALTER TABLE ORDERS 
       ADD FOREIGN KEY (Customer_ID) REFERENCES CUSTOMERS (ID);

刪除外鍵約束:

要?jiǎng)h除外鍵約束的話,語(yǔ)法如下所示:

    ALTER TABLE ORDERS
       DROP FOREIGN KEY;

CHECK 約束

CHECK 約束使用某一條件來(lái)對(duì)記錄中的值進(jìn)行檢查。如果條件最終為假(false),即約束條件不能得到滿足,則該記錄不能寫入數(shù)據(jù)表中。

示例:

例如,下述 SQL 語(yǔ)句創(chuàng)建了一個(gè)名為 CUSTOMERS 的新表,并為其添加了五個(gè)字段。在此,我們?yōu)?AGE 字段設(shè)置了 CHECK 約束,以拒絕任何年齡低于 18 的顧客:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL CHECK (AGE >= 18),
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

如果 CUSTOMERS 表已經(jīng)存在,再要為 AGE 字段設(shè)置 CHECK 約束的話,就需要像下面這樣寫 SQL 語(yǔ)句:

    ALTER TABLE CUSTOMERS
       MODIFY AGE INT NOT NULL CHECK (AGE >= 18 );

或者也可以使用下面的語(yǔ)法,該語(yǔ)法還支持對(duì)作用于多個(gè)字段的約束命名:

    ALTER TABLE CUSTOMERS
       ADD CONSTRAINT myCheckConstraint CHECK(AGE >= 18);

刪除 CHECK 約束:

要?jiǎng)h除 CHECK 約束的話,請(qǐng)使用下面的 SQL 語(yǔ)句,不過(guò)該語(yǔ)句在 MySQL 中不起作用:

    ALTER TABLE CUSTOMERS
       DROP CONSTRAINT myCheckConstraint;

索引

索引用于在數(shù)據(jù)庫(kù)中快速地創(chuàng)建和檢索數(shù)據(jù)。索引可以由表中的一個(gè)或者多個(gè)字段創(chuàng)建。創(chuàng)建索引時(shí),每一行都會(huì)獲得一個(gè) ROWID(在數(shù)據(jù)進(jìn)行排序之前)。

合理運(yùn)用索引可以提高大型數(shù)據(jù)庫(kù)的性能。但是,創(chuàng)建索引之前還是要三思而后行。為哪些字段創(chuàng)建索引,則取決于 SQL 查詢最常用到到哪些字段。

示例:

例如,下面的 SQL 語(yǔ)句創(chuàng)建了一個(gè)名為 CUSTOMERS 的新表,并為其添加了五個(gè)字段:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25) ,
           SALARY   DECIMAL (18, 2),       
           PRIMARY KEY (ID)
    );

現(xiàn)在,你就可以使用下面的語(yǔ)法來(lái)為一個(gè)或者多個(gè)字段創(chuàng)建索引了:

    CREATE INDEX index_name
        ON table_name ( column1, column2.....);

例如,可以在 AGE 字段上創(chuàng)建索引,以優(yōu)化對(duì)特定年齡的顧客的查詢,其語(yǔ)法如下所示:

    CREATE INDEX idx_age
        ON CUSTOMERS ( AGE );

刪除索引約束:

要?jiǎng)h除索引約束的話,可以使用下面的 SQL 語(yǔ)句:

    ALTER TABLE CUSTOMERS
       DROP INDEX idx_age;

數(shù)據(jù)完整性

下面幾類數(shù)據(jù)完整性存在于各個(gè) RDBMS 中:

  • 實(shí)體完整性:表中沒(méi)有重復(fù)的行
  • 域完整性:通過(guò)限制數(shù)據(jù)類型、格式或者范圍來(lái)保證給定列的數(shù)據(jù)有效性
  • 參照完整性:不能刪除被其他記錄引用的行
  • 用戶定義完整性:施加某些不屬于上述三種完整性的業(yè)務(wù)規(guī)則

數(shù)據(jù)庫(kù)規(guī)范化

數(shù)據(jù)庫(kù)規(guī)范化指的是對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)進(jìn)行有效組織的過(guò)程。對(duì)數(shù)據(jù)庫(kù)進(jìn)行規(guī)范化主要有兩個(gè)目的:

  • 消除冗余數(shù)據(jù),例如相同數(shù)據(jù)出現(xiàn)在不同的表中。
  • 保證數(shù)據(jù)依賴性合理。

這兩個(gè)目標(biāo)都值得我們努力,因?yàn)樗鼈兛梢詼p少數(shù)據(jù)的空間占用,并確保了數(shù)據(jù)的邏輯完備。規(guī)范化包含一系列的指導(dǎo)方針,以幫助你創(chuàng)建出優(yōu)良的數(shù)據(jù)庫(kù)結(jié)構(gòu)。

規(guī)范化指導(dǎo)方針?lè)譃閹追N范式(form),你可以把范式想做是數(shù)據(jù)庫(kù)的格式或者其結(jié)構(gòu)的布局方式。使用范式的目標(biāo)是對(duì)數(shù)據(jù)庫(kù)結(jié)構(gòu)進(jìn)行整理,從而使其遵循第一范式,接著是第二范式,最終遵循第三范式。

要不要更進(jìn)一步到達(dá)第四范式、第五范式甚至更高的范式取決于你。一般來(lái)說(shuō),第三范式足矣。

第一范式(1NF)

第一范式設(shè)定了對(duì)數(shù)據(jù)庫(kù)進(jìn)行組織的最基本的規(guī)范:

  • 定義需要的數(shù)據(jù)項(xiàng),因?yàn)檫@些項(xiàng)將會(huì)成為數(shù)據(jù)表中的字段。將相關(guān)的數(shù)據(jù)項(xiàng)放在一個(gè)表中。
  • 保證不存在重復(fù)的數(shù)據(jù)。
  • 保證有一個(gè)主鍵。

1NF 的第一規(guī)則:

你必須定義所需的數(shù)據(jù)項(xiàng)。這意味著查看要存儲(chǔ)的數(shù)據(jù),按照字段對(duì)其進(jìn)行組織,定義各個(gè)字段的數(shù)據(jù)類型,最終將相關(guān)的字段放在同一個(gè)表中。

例如,將所有與會(huì)議地點(diǎn)相關(guān)的字段放在 Location 表中,將所有同與會(huì)成員相關(guān)的字段放在 MemberDetails 表中等等。

1NF 的第二規(guī)則:

下一步是保證不存在重復(fù)的數(shù)據(jù)集合??紤]如下的數(shù)據(jù)表:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25),
           ORDERS   VARCHAR(155)
    );

如果我們用同一個(gè)顧客的多筆訂單來(lái)填充該表,將會(huì)得到類似下面的數(shù)據(jù)表:

ID NAME AGE ADDRESS ORDERS
100 Sachin 36 Lower West Side Cannon XL-200
100 Sachin 36 Lower West Side Battery XL-200
100 Sachin 36 Lower West Side Tripod Large

但是,按照 1NF 我們必須保證沒(méi)有重復(fù)的數(shù)據(jù)集合。所以,可以將上表分成兩部分,然后使用一個(gè)鍵將兩個(gè)表連接起來(lái)。

CUSTOMERS 表:

    CREATE TABLE CUSTOMERS(
           ID   INT              NOT NULL,
           NAME VARCHAR (20)     NOT NULL,
           AGE  INT              NOT NULL,
           ADDRESS  CHAR (25),
           PRIMARY KEY (ID)
    );

表中記錄如下:

ID NAME AGE ADDRESS
100 Sachin 36 Lower West Side

ORDERS 表:

    CREATE TABLE ORDERS(
           ID   INT              NOT NULL,
           CUSTOMER_ID INT       NOT NULL,
           ORDERS   VARCHAR(155),
           PRIMARY KEY (ID)
    );

表中記錄如下:

ID CUSTOMER_ID ORDERS
10 100 Cannon XL-200
11 100 Battery XL-200
12 100 Tripod Large

1NF 的第三規(guī)則:

第一范式的最后一條規(guī)則是,為每一個(gè)數(shù)據(jù)表創(chuàng)建一個(gè)主鍵。

第二范式(2NF)

第二范式規(guī)定,數(shù)據(jù)表必須符合第一范式,并且所有字段與主鍵之間不存在部分依賴關(guān)系。

考慮顧客與訂單之間的關(guān)系,你可能會(huì)想要存儲(chǔ)顧客 ID、顧客姓名、訂單 ID、訂單明細(xì)以及購(gòu)買日期:

    CREATE TABLE CUSTOMERS(
           CUST_ID    INT              NOT NULL,
           CUST_NAME VARCHAR (20)      NOT NULL,
           ORDER_ID   INT              NOT NULL,
           ORDER_DETAIL VARCHAR (20)  NOT NULL,
           SALE_DATE  DATETIME,
           PRIMARY KEY (CUST_ID, ORDER_ID)
    );

該表符合第一范式,因?yàn)樗鼭M足第一范式的所有規(guī)則。表中的主鍵有 CUST_ID 和 ORDER_ID。二者一起作為主鍵,我們假定同一個(gè)顧客不會(huì)購(gòu)買相同的東西。

然而,該表不符合第二范式,因?yàn)楸碇械淖侄魏椭麈I之間存在部分依賴關(guān)系。CUST_NAME 依賴于 CUST_ID,而 CUST_NAME 和所購(gòu)物品之間沒(méi)有直接的聯(lián)系。訂單明細(xì)和購(gòu)買日期依賴于 ORDER_ID,但是他們并不依賴于 CUST_ID,因?yàn)?CUST_ID 和 ORDER_DETAIL 以及 SALE_DATE 之間并不存在聯(lián)系。

要使該表遵守第二范式,你需要將其分為三個(gè)數(shù)據(jù)表。

首先,創(chuàng)建如下的數(shù)據(jù)表來(lái)保存客戶詳情:

    CREATE TABLE CUSTOMERS(
           CUST_ID    INT              NOT NULL,
           CUST_NAME VARCHAR (20)      NOT NULL,
           PRIMARY KEY (CUST_ID)
    );

接著創(chuàng)建一個(gè)表來(lái)存儲(chǔ)每個(gè)訂單的詳細(xì)信息:

    CREATE TABLE ORDERS(
           ORDER_ID   INT              NOT NULL,
           ORDER_DETAIL VARCHAR (20)  NOT NULL,
           PRIMARY KEY (ORDER_ID)
    );

最后,創(chuàng)建一個(gè)表來(lái)存儲(chǔ) CUST_ID 和 ORDER_ID 來(lái)記錄同一顧客的所有訂單:

    CREATE TABLE CUSTMERORDERS(
           CUST_ID    INT              NOT NULL,
           ORDER_ID   INT              NOT NULL,
           SALE_DATE  DATETIME,
           PRIMARY KEY (CUST_ID, ORDER_ID)
    );

第三范式(3NF)

一個(gè)數(shù)據(jù)表符合第三范式,當(dāng)其滿足:

  • 符合第二范式;
  • 所有的非主鍵字段都依賴于主鍵;

非主鍵字段之間的依賴關(guān)系存在于數(shù)據(jù)之中。例如下表中,街道(street)、城市(city)和省份(state)顯然與郵政編碼(zip Code)之間存在密不可分的關(guān)系。

    CREATE TABLE CUSTOMERS(
           CUST_ID       INT              NOT NULL,
           CUST_NAME     VARCHAR (20)      NOT NULL,
           DOB           DATE,
           STREET        VARCHAR(200),
           CITY          VARCHAR(100),
           STATE         VARCHAR(100),
           ZIP           VARCHAR(12),
           EMAIL_ID      VARCHAR(256),
           PRIMARY KEY (CUST_ID)
    );

郵政編碼和地址之間的關(guān)系稱作傳遞相關(guān)性(transitive dependency)。要使得數(shù)據(jù)表符合第三范式,需要將街道、城市、省份等字段移到另一張表中,可以稱其為 Zip Code 表:

    CREATE TABLE ADDRESS(
           ZIP           VARCHAR(12),
           STREET        VARCHAR(200),
           CITY          VARCHAR(100),
           STATE         VARCHAR(100),
           PRIMARY KEY (ZIP)
    );

接著,按照如下方式更改 CUSTOMERS 表:

    CREATE TABLE CUSTOMERS(
           CUST_ID       INT              NOT NULL,
           CUST_NAME     VARCHAR (20)      NOT NULL,
           DOB           DATE,
           ZIP           VARCHAR(12),
           EMAIL_ID      VARCHAR(256),
           PRIMARY KEY (CUST_ID)
    );

移除傳遞相關(guān)性可以起到事半功倍的效果。首先是數(shù)據(jù)冗余度降低了,數(shù)據(jù)庫(kù)體積因此縮小。第二個(gè)好處是保證數(shù)據(jù)完整性。當(dāng)重復(fù)數(shù)據(jù)改變的時(shí)候,很有可能只更新部分?jǐn)?shù)據(jù),尤其是當(dāng)其分布在數(shù)據(jù)庫(kù)的各個(gè)地方的情況下。例如,如果地址和郵政編碼分別存儲(chǔ)在三個(gè)或者四個(gè)不同的數(shù)據(jù)表中,那么任何對(duì)郵編的改變,都需要對(duì)這三個(gè)或者四個(gè)表同時(shí)進(jìn)行更改。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)