Schema_(数据库)

**綱要**（英語：**Schema**，又稱**模式**），香港和中國大陸翻譯為**模式**或**架構**，在資料庫系統中是形式語言描述的一種結構，是對象的集合，可包含各種對象如：表、欄位、關係模型、視圖、索引、包、存儲過程、子程序、隊列、觸發器、數據類型、序列、物化視圖、同義詞（synonym）、database link、directory、XML schema 等。

模式的益處：

* 允許多個用戶使用一個資料庫而不會干擾其它用戶。
* 把資料庫對象組織成邏輯組，讓它們更便於管理。
* 第三方的應用可以放在不同的模式中，不會和其它對象的名字衝突。

## Oracle 資料庫實現

在 Oracle 資料庫中，**schema object** 是一類邏輯資料庫存儲結構。

Oracle 的資料庫會為每個在資料庫的**用戶**關聯一個獨立的 schema。

schema 包括有一堆 schema objects 的集合。schema objects 的例子包括有：

* 資料庫表
* 視圖
* 序列
* 異名
* 資料庫索引
* 資料庫叢集
* 資料庫連結
* 快照
* 存儲程序
* functions
* packages

與此同時，非 schema objects 可能包括：

* users
* roles
* contexts
* directory objects

Schema objects 跟磁碟上用來儲存資料的物理檔案並沒有一對一的關連。不過，Oracle 資料庫會將 schema objects 以虛擬的邏輯形式儲存在資料庫的表空間裡。每一件 schema object 的數據在物理上如同其他表空間的內容一樣，儲存在表空間所屬的其中一個 datafile 裡。部分 objects（例如：表、索引、叢集等）所佔的空間，資料庫管理員可控制 Oracle 的 RDBMS 可如何在表空間的 datafile 內如何分配與 schema object。

schemas 與表空間之間沒有必然的關係：表空間可以包含來自不同 schema 的 objects，並且單個 schema 的 object 可以位於不同的表空間中。

## SQL Server 資料庫實現

SQL Server 資料庫把 schema 譯作「架構」。架構是資料庫中對象的容器。架構是形成單個命名空間的資料庫實體的集合。命名空間是一個集合，其中每個元素的名稱都是唯一的。默認架構 DBO。訪問默認架構中的對象時，不需要指定架構的名稱。微軟建議使用兩段式對象名稱：

```
 架構名.對象名
```

創建架構的語句舉例：

```
 CREATE SCHEMA mySchema AUTHORIZATION user1
      CREATE TABLE myTable1(source int, cost int, partnumber int)
      GRANT SELECT TO user2
      Deny SELECT TO AnotherUser3;
```

上述語句創建一個架構 mySchema，所有者為 user1，包含表 myTable1，授予 user2 以 SELECT 權限，拒絕給 AnotherUser3 以 SELECT 權限。

授予 / 撤銷用戶對架構的所有權：

```
GRANT INSERT ON SCHEMA ::mySchema1 To myUser2;
REVOKE INSERT ON SCHEMA ::mySchema1 To myUser2;
```

把對象從一個架構移動到另一個架構（必須同個資料庫）：

```
ALTER SCHEMA mySchema2 TRANSFER mySchema1.myTable1;
```

刪除一個架構，該架構不能包含對象：

```
DROP SCHEMA mySchema3;
```

### 歷史

在 SQL Server 2000 中，資料庫用戶和架構是隱式同一。每個資料庫用戶都是與該用戶同名的架構的所有者。對象的所有者在功能上與包含它的架構所有者相同。因而，SQL Server 2000 中的完全限定名稱的「架構」也是資料庫中的用戶。

SQL Server 2005 中，架構獨立於創建它們的資料庫用戶而存在。多個用戶可以共享一個默認架構進行統一的名稱解析。 刪除資料庫用戶不需要重命名該用戶架構所包含的對象。完全限定的對象名稱現在包含四部分：server.database.schema.object。如果未定義 DEFAULT\_SCHEMA 選項設置和更改默認架構，則資料庫用戶將把 DBO 作為其默認架構。

## MySQL 資料庫實現

MySQL 中 Schema 等價於 資料庫。

CREATE SCHEMA 是 CREATE DATABASE 的同義詞。

## PostgreSQL 資料庫實現

PostgreSQL 資料庫集群可以有一個或多個命名的資料庫。用戶和用戶組在整個集群的範圍內是共享的，即不能有同名用戶。任何給定的客戶連接（connection）都只能訪問一個資料庫。

一個資料庫包含一個或多個命名的模式， 模式包含其它命名的對象，如表、數據類型、函數、操作符等。在不同的模式里使用同名的對象不會導致衝突。例如，schema1 和 schemaA 都可以包含叫做 mytable 的表。一個用戶可以訪問所連接的資料庫中的任意模式中的對象，只要有這個權限。

## Apache Derby 資料庫實現

Apache Derby 資料庫（即 Java DB）的任何 connection 的當前 schema，默認是對應於該用戶名的一個 schema。如果無用戶名被提供，那麼當前用戶名與當前 schema 預設是 APP。

但即使當前 schema 被設置為用戶名，這個 schema 仍然可能不存在。一個 schema 只能被創建：通過 CREATE SCHEMA 語句顯式創建或者創建一個對象（例如表等）來隱式創建。

APP schema 總是存在，不需要創建。

如果你的程序試圖訪問當前 schema 但該 schema 下沒有創建任何對象，就會遇到「schema not exists」錯誤。

## SQL 實現

ISO/IEC 9075-1 SQL 標準中將 schema 定義為描述符的持久命名集合（a persistent, named collection of descriptors）。

創建一個 schema:

```
create schema demo_schema;
```

在指定模式里創建表：

```
CREATE TABLE myschema.mytable (
   ...
);
```

刪除一個空的 schema：

```
drop schema myschema;
```

刪除一個模式以及模式裡面所有的對象：

```
drop schema MySchema CASCADE;
```

默認的 pulic schema：創建表時，如果沒有指定 schema，則會自動被歸屬到資料庫的「public」的模式中。下面兩種創建表的方式是等效的：

```
CREATE TABLE tableName(...);
CREATE TABLE public.tableName(...);
```

### 模式的權限

用戶默認是看不到模式中不屬於他們所有的對象。

模式權限：

* USAGE 權限
* CREATE 權限：在別人的模式里創建對象。預設時，每個用戶在 public 模式上有 CREATE 權限。撤銷這個權限：REVOKE CREATE ON public FROM PUBLIC; （第一個 "public" 是模式，第二個 "public" 意思是 "所有用戶"。 第一句里它是個標識符，而第二句里是個關鍵字，所以有不同的大小寫）

### 模式搜索路徑

系統使用一個模式的列表作為搜索路徑來解析一個表屬於哪個模式。搜索路徑中的第一個模式是當前模式；CREATE TABLE 沒有聲明模式名的時候，新建的表屬於當前模式。

查看搜索路徑：

```
SHOW search_path; 'PostgreSQL数据库
```

設置搜索路徑

```
SET search_path TO myschema,public; 'PostgreSQL数据库
```

## 參考文獻

## 參看

* 數據元
* 數據映射
* 資料庫設計
* ER 模型
* 知識表示
* Object-role modeling
* Schema matching
* Three-schema approach

## 外部連結

* Tip/Trick: Online Database Schema Samples Library （頁面存檔備份，存於網際網路檔案館）
* Database Schema Samples
* Designing the Star Schema Database