?
This document uses PHP Chinese website manual Release
一個(gè)PostgreSQL數(shù)據(jù)庫(kù)集群包含一個(gè)或多個(gè)已 命名數(shù)據(jù)庫(kù)。用戶和用戶組在整個(gè)集群范圍內(nèi)是共享的,但是其它數(shù)據(jù)并不共享。 任何與服務(wù)器連接的客戶都只能訪問(wèn)那個(gè)在連接請(qǐng)求里聲明的數(shù)據(jù)庫(kù)。
Note: 集群中的用戶并不一定要有訪問(wèn)集群內(nèi)所有數(shù)據(jù)庫(kù)的權(quán)限。共享用戶名的意思是 不能有重名用戶。假定同一個(gè)集群里有兩個(gè)數(shù)據(jù)庫(kù)和一個(gè)joe用戶, 系統(tǒng)可以配置成只允許joe訪問(wèn)其中的一個(gè)數(shù)據(jù)庫(kù)
一個(gè)數(shù)據(jù)庫(kù)包含一個(gè)或多個(gè)已命名的schemas,模式又包含表。 模式還可以包含其它對(duì)象,包括數(shù)據(jù)類型、函數(shù)、操作符等。同一個(gè)對(duì)象名 可以在不同的模式里使用而不會(huì)導(dǎo)致沖突;比如,schema1和 myschema都可以包含一個(gè)名為mytable的表。 和數(shù)據(jù)庫(kù)不同,模式不是嚴(yán)格分離的:只要有權(quán)限,一個(gè)用戶可以訪問(wèn)他所 連接的數(shù)據(jù)庫(kù)中的任意模式中的對(duì)象。
我們需要模式的原因有好多:
允許多個(gè)用戶使用一個(gè)數(shù)據(jù)庫(kù)而不會(huì)干擾其它用戶。
把數(shù)據(jù)庫(kù)對(duì)象組織成邏輯組,讓它們更便于管理。
第三方的應(yīng)用可以放在不同的模式中,這樣它們就不會(huì)和其它對(duì)象的名字沖突。
模式類似于操作系統(tǒng)層次的目錄,只不過(guò)模式不能嵌套。
要?jiǎng)?chuàng)建一個(gè)模式,使用CREATE SCHEMA命令。給出你選擇的模式名字。比如:
CREATE SCHEMA myschema;
要?jiǎng)?chuàng)建或者訪問(wèn)在模式中的對(duì)象,寫出一個(gè)受修飾的名字, 這個(gè)名字包含模式名以及表名,它們之間用一個(gè)句點(diǎn)分開(kāi):
schema.table
這個(gè)方式在任何需要表名字的地方都可用,包括后面章節(jié)討論的表修改命令 和數(shù)據(jù)訪問(wèn)命令。出于簡(jiǎn)化,我們將只討論表,這個(gè)概念適用于所有其它已 命名對(duì)象類型,比如數(shù)據(jù)類型和函數(shù)。
實(shí)際上,更一般的語(yǔ)法是
database.schema.table
這個(gè)語(yǔ)法也可以使用,但目前它只是為了和SQL標(biāo)準(zhǔn)形式上上兼容。 如果你寫了一個(gè)數(shù)據(jù)庫(kù)名,那么它必須和你當(dāng)前連接的數(shù)據(jù)庫(kù)同名。
要在新模式里創(chuàng)建一個(gè)表,用
CREATE TABLE myschema.mytable ( ... );
如果一個(gè)模式是空的(所有它里面的對(duì)象都已經(jīng)刪除),那么刪除一個(gè)模式的命令如下:
DROP SCHEMA myschema;
要?jiǎng)h除一個(gè)模式及其包含的所有對(duì)象,可以使用:
DROP SCHEMA myschema CASCADE;
參閱Section 5.11獲取對(duì)隱藏在這些動(dòng)作背后的東西的一般機(jī)制的描述。
通常你想創(chuàng)建一個(gè)他人擁有的模式(因?yàn)檫@是一種限制用戶在定義良好的模式中的活動(dòng)的方法)。 其語(yǔ)法如下:
CREATE SCHEMA schemaname AUTHORIZATION username;
你甚至可以省略模式名字,這時(shí)模式名將和用戶名同名。參閱 Section 5.7.6獲取這種情況的適用場(chǎng)合。
以pg_開(kāi)頭的模式名是保留給系統(tǒng)使用的,用戶不能創(chuàng)建這樣的名字。
在前面的小節(jié)里,我們沒(méi)有聲明任何模式名字就創(chuàng)建了表。缺省時(shí),這樣的表 (以及其它對(duì)象)都自動(dòng)放到一個(gè)叫做""public""的模式中去了。 每個(gè)新數(shù)據(jù)庫(kù)都包含一個(gè)這樣的模式。因此,下面的命令是等效的:
CREATE TABLE products ( ... );
and:
CREATE TABLE public.products ( ... );
全稱的名字寫起來(lái)非常費(fèi)勁,并且我們最好不要在應(yīng)用里直接寫上特定的模式名。 因此,表通常都是用未修飾的名字引用的,這樣的名字里只有表名字。 系統(tǒng)通過(guò)查找一個(gè)搜索路徑來(lái)判斷一個(gè)表究竟是哪個(gè)表,這個(gè)路徑是一個(gè)需要查找的模式名列表。 在搜索路徑里找到的第一個(gè)表將被使用。如果在搜索路徑中沒(méi)有找到表,那么就報(bào)告一個(gè)錯(cuò)誤 (即使在數(shù)據(jù)庫(kù)里的其它模式中存在此表也如此)。
在搜索路徑中的第一個(gè)模式叫做"當(dāng)前模式"。除了是搜索的第一個(gè)模式之外,它還是在CREATE TABLE沒(méi)有聲明模式名的時(shí)候,新建表的默認(rèn)所在地。
要顯示當(dāng)前搜索路徑,使用下面的命令:
SHOW search_path;
在缺省的設(shè)置中,返回下面的東西:
search_path -------------- "$user",public
第一個(gè)元素聲明搜索和當(dāng)前用戶同名的模式。因?yàn)檫€沒(méi)有這樣的模式存在,所以這條記錄被忽略。第二個(gè)元素指向我們已經(jīng)看過(guò)的公共模式。
搜索路徑中第一個(gè)存在的模式是創(chuàng)建新對(duì)象的缺省位置。這就是為什么缺省的對(duì)象都會(huì)創(chuàng)建在 public 模式里的原因。如果在其它環(huán)境中引用對(duì)象且沒(méi)有模式修飾,那么系統(tǒng)會(huì)遍歷搜索路徑,直到找到一個(gè)匹配的對(duì)象。因此,在缺省的配置里,任何未修飾的訪問(wèn)只能引用 public 模式。
要設(shè)置模式的搜索路徑,可以用(省略了$user是因?yàn)椴⒉涣⒓葱枰?
SET search_path TO myschema,public;
然后我們就可以不使用模式修飾來(lái)訪問(wèn)表了:
DROP TABLE mytable;
同樣,因?yàn)?tt class="LITERAL">myschema是路徑中的第一個(gè)元素,新對(duì)象缺省時(shí)將創(chuàng)建在這里。
我們也可以寫成:
SET search_path TO myschema;
然后我們?nèi)绻幻鞔_修飾的話,就不能再訪問(wèn)public模式了。public模式?jīng)]有任何特殊之處,只不過(guò)它缺省時(shí)就存在。我們也可以刪除它。
又見(jiàn)Section 9.23以獲取其它操作模式搜索路徑的方法。
搜索路徑對(duì)于數(shù)據(jù)類型名、函數(shù)名、操作符名的運(yùn)作方式和表名完全相同。數(shù)據(jù)類型和函數(shù)名可以像表名一樣加以修飾。 如果你需要在表達(dá)式里寫一個(gè)有模式修飾的操作符,你必須這么寫:
OPERATOR(schema.operator)
這樣是為了避免語(yǔ)法歧義。下面是一個(gè)例子:
SELECT 3 OPERATOR(pg_catalog.+) 4;
實(shí)踐中我們通常依賴搜索路徑尋找操作符,這樣就不用寫這么難看的東西了。
缺省時(shí),用戶無(wú)法訪問(wèn)模式中不屬于他們所有的對(duì)象。為了讓他們能夠訪問(wèn), 模式的所有者需要在模式上賦予他們USAGE權(quán)限。 為了讓用戶使用模式中的對(duì)象,我們可能需要賦予適合該對(duì)象的額外權(quán)限。
用戶也可以在別人的模式里創(chuàng)建對(duì)象。要允許這么做, 需要被賦予在該模式上的CREATE權(quán)限。請(qǐng)注意,缺省時(shí)每個(gè)人都在public。模式上有CREATE和USAGE權(quán)限。 這樣就允許所有可以連接到聲明數(shù)據(jù)庫(kù)上的用戶在這里創(chuàng)建對(duì)象。如果你不打算這么做,可以撤銷這個(gè)權(quán)限:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
第一個(gè)"public"是模式,第二個(gè)"public"意思是 "every user"。第一句里它是個(gè)標(biāo)識(shí)符, 而第二句里是個(gè)關(guān)鍵字,所以有不同的大小寫。 記住我們?cè)赟ection 4.1.1里面說(shuō)過(guò)的原則。
除了public和用戶創(chuàng)建的模式之外,每個(gè)數(shù)據(jù)庫(kù)都包含一個(gè)pg_catalog模式, 它包含系統(tǒng)表和所有內(nèi)置數(shù)據(jù)類型、函數(shù)、操作符。pg_catalog總是搜索路徑中的一部分。 如果它沒(méi)有明確出現(xiàn)在路徑中,那么它隱含地在所有路徑之前搜索。這樣就保證了內(nèi)置名字總是可以被搜索。 不過(guò),你可以明確地把pg_catalog放在搜索路徑之后,如果你想使用用戶自定義的名字覆蓋內(nèi)置的名字的話。
在PostgreSQL版本 7.3 之前,以pg_開(kāi)頭的表名字是保留的。這個(gè)規(guī)則現(xiàn)在不正確了:如果必要, 你可以創(chuàng)建這樣的表名字,只要是在非系統(tǒng)模式里。不過(guò),我們最好還是不要使用這樣的名字,以保證自己將來(lái)不會(huì)和新版本沖突: 那些版本也許會(huì)定義一些和你的表同名的表(在缺省搜索路徑中,一個(gè)對(duì)你的表的無(wú)修飾引用將解析為系統(tǒng)表)。 系統(tǒng)表將繼續(xù)遵循以pg_開(kāi)頭的傳統(tǒng),因此,只要你的表不是以pg_開(kāi)頭,就不會(huì)和無(wú)修飾的用戶表名字沖突。
模式可以用多種方式組織數(shù)據(jù)。下面是一些建議使用的模式,它們也很容易在缺省配置中得到支持:
如果沒(méi)有創(chuàng)建任何模式,那么所有用戶隱含都訪問(wèn)public模式。這樣就模擬了沒(méi)有模式的時(shí)候的情景。這種設(shè)置建議主要用在只有一個(gè)用戶或者數(shù)據(jù)庫(kù)里只有幾個(gè)可信用戶的情形。這樣的設(shè)置也允許我們平滑地從無(wú)模式的環(huán)境過(guò)渡。
你可以為每個(gè)用戶創(chuàng)建一個(gè)模式,名字和用戶相同。要記得缺省的搜索路徑從$user開(kāi)始, 它會(huì)解析為用戶名。因此,如果每個(gè)用戶都有一個(gè)獨(dú)立的模式,那么他們?nèi)笔r(shí)訪問(wèn)他們自己的模式。
如果你使用了這樣的設(shè)置, 那么你可能還想撤銷對(duì)public模式的訪問(wèn)(或者刪除它),這樣,用戶就真的限制于他們自己的模式了。
要安裝共享的應(yīng)用(被所有人使用的表、第三方提供的額外函數(shù)等等),我們可以把它們放到獨(dú)立的模式中。只要記得給需要訪問(wèn)它們的用戶賦予合適的權(quán)限就可以了。然后用戶就可以通過(guò)用一個(gè)模式名修飾來(lái)使用這些額外的對(duì)象,或者他們可以把額外的模式放到他們的搜索路徑中。
在SQL標(biāo)準(zhǔn)里,在同一個(gè)模式里的對(duì)象被不同的用戶所有的概念是不存在的。而且, 有些實(shí)現(xiàn)不允許你創(chuàng)建和它們的所有者不同名的模式。實(shí)際上,模式和用戶的概念在 那些只實(shí)現(xiàn)了標(biāo)準(zhǔn)中規(guī)定的基本模式支持的數(shù)據(jù)庫(kù)系統(tǒng)里幾乎是一樣的。因此,許多用戶考慮對(duì)名字加以修飾, 使它們真正由username.tablename組成。如果你為每個(gè)用戶都創(chuàng)建了一個(gè)模式,這實(shí)際上就是PostgreSQL的行為。
同樣,在SQL標(biāo)準(zhǔn)里也沒(méi)有public模式的概念。為了最大限度地遵循標(biāo)準(zhǔn), 你不應(yīng)該使用(可能甚至是應(yīng)該刪除)public模式。
當(dāng)然,有些數(shù)據(jù)庫(kù)系統(tǒng)可能根本沒(méi)有模式,或者是通過(guò)允許跨數(shù)據(jù)庫(kù)訪問(wèn)來(lái)提供模式的功能。如果你需要在這些系統(tǒng)上干活,那么為了最大限度的移植性,應(yīng)該根本不使用模式。