W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
一個(gè)PostgreSQL數(shù)據(jù)庫集簇中包含一個(gè)或更多命名的數(shù)據(jù)庫。 角色和一些其他對(duì)象類型被整個(gè)集簇共享,連接到服務(wù)器的客戶端只能訪問單個(gè)數(shù)據(jù)庫中的數(shù)據(jù),在連接請(qǐng)求中指定的那一個(gè)。
一個(gè)集簇的用戶并不必?fù)碛性L問集簇中每一個(gè)數(shù)據(jù)庫的權(quán)限。
角色名的共享意味著不可能在同一個(gè)集簇中出現(xiàn)重名的不同角色,例如兩個(gè)數(shù)據(jù)庫中都有叫joe
的用戶。
但系統(tǒng)可以被配置為只允許joe
訪問某些數(shù)據(jù)庫。
一個(gè)數(shù)據(jù)庫包含一個(gè)或多個(gè)命名模式,模式中包含著表。模式還包含其他類型的命名對(duì)象,包括數(shù)據(jù)類型、函數(shù)和操作符。相同的對(duì)象名稱可以被用于不同的模式中二不會(huì)出現(xiàn)沖突,例如schema1
和myschema
都可以包含名為mytable
的表。和數(shù)據(jù)庫不同,模式并不是被嚴(yán)格地隔離:一個(gè)用戶可以訪問他們所連接的數(shù)據(jù)庫中的所有模式內(nèi)的對(duì)象,只要他們有足夠的權(quán)限。
下面是一些使用方案的原因:
允許多個(gè)用戶使用一個(gè)數(shù)據(jù)庫并且不會(huì)互相干擾。
將數(shù)據(jù)庫對(duì)象組織成邏輯組以便更容易管理。
第三方應(yīng)用的對(duì)象可以放在獨(dú)立的模式中,這樣它們就不會(huì)與其他對(duì)象的名稱發(fā)生沖突。
模式類似于操作系統(tǒng)層的目錄,但是模式不能嵌套。
要?jiǎng)?chuàng)建一個(gè)模式,可使用CREATE SCHEMA命令,并且給出選擇的模式名稱。例如:
CREATE SCHEMA myschema;
在一個(gè)模式中創(chuàng)建或訪問對(duì)象,需要使用由模式名和表名構(gòu)成的限定名,模式名和表名之間以點(diǎn)號(hào)分隔:
schema
.
table
在任何需要一個(gè)表名的地方都可以這樣用,包括表修改命令和后續(xù)章節(jié)要討論的數(shù)據(jù)訪問命令(為了簡(jiǎn)潔我們?cè)谶@里只談到表,但是這種方式對(duì)其他類型的命名對(duì)象同樣有效,例如類型和函數(shù))。
事實(shí)上,還有更加通用的語法:
database
.
schema
.
table
也可以使用,但是目前它只是在形式上與SQL標(biāo)準(zhǔn)兼容。如果我們寫一個(gè)數(shù)據(jù)庫名稱,它必須是我們正在連接的數(shù)據(jù)庫。
因此,如果要在一個(gè)新模式中創(chuàng)建一個(gè)表,可用:
CREATE TABLE myschema.mytable (
...
);
要?jiǎng)h除一個(gè)為空的模式(其中的所有對(duì)象已經(jīng)被刪除),可用:
DROP SCHEMA myschema;
要?jiǎng)h除一個(gè)模式以及其中包含的所有對(duì)象,可用:
DROP SCHEMA myschema CASCADE;
有關(guān)于此的更一般的機(jī)制請(qǐng)參見第 5.14 節(jié)。
我們常常希望創(chuàng)建一個(gè)由其他人所擁有的模式(因?yàn)檫@是將用戶動(dòng)作限制在良定義的名字空間中的方法之一)。其語法是:
CREATE SCHEMA schema_name
AUTHORIZATION user_name
;
我們甚至可以省略模式名稱,在此種情況下模式名稱將會(huì)使用用戶名,參見本文中的“5.9.6. 使用模式”。
以pg_
開頭的模式名被保留用于系統(tǒng)目的,所以不能被用戶所創(chuàng)建。
在前面的小節(jié)中,我們創(chuàng)建的表都沒有指定任何模式名稱。默認(rèn)情況下這些表(以及其他對(duì)象)會(huì)自動(dòng)的被放入一個(gè)名為“public”的模式中。任何新數(shù)據(jù)庫都包含這樣一個(gè)模式。因此,下面的命令是等效的:
CREATE TABLE products ( ... );
以及:
CREATE TABLE public.products ( ... );
限定名寫起來很冗長(zhǎng),通常最好不要把一個(gè)特定模式名拉到應(yīng)用中。因此,表名通常被使用非限定名來引用,它只由表名構(gòu)成。系統(tǒng)將沿著一條搜索路徑來決定該名稱指的是哪個(gè)表,搜索路徑是一個(gè)進(jìn)行查看的模式列表。 搜索路徑中第一個(gè)匹配的表將被認(rèn)為是所需要的。如果在搜索路徑中沒有任何匹配,即使在數(shù)據(jù)庫的其他模式中存在匹配的表名也將會(huì)報(bào)告一個(gè)錯(cuò)誤。
在不同方案中創(chuàng)建命名相同的對(duì)象的能力使得編寫每次都準(zhǔn)確引用相同對(duì)象的查詢變得復(fù)雜。這也使得用戶有可能更改其他用戶查詢的行為,不管是出于惡意還是無意。由于未經(jīng)限定的名稱在查詢中以及在PostgreSQL內(nèi)部的廣泛使用,在search_path
中增加一個(gè)方案實(shí)際上是信任所有在該方案中具有CREATE
特權(quán)的用戶。在你運(yùn)行一個(gè)普通查詢時(shí),惡意用戶可以在你的搜索路徑中的以方案中創(chuàng)建能夠奪取控制權(quán)并且執(zhí)行任意SQL函數(shù)的對(duì)象,而這些事情就像是你在執(zhí)行一樣。
搜索路徑中的第一個(gè)模式被稱為當(dāng)前模式。除了是第一個(gè)被搜索的模式外,如果CREATE TABLE
命令沒有指定模式名,它將是新創(chuàng)建表所在的模式。
要顯示當(dāng)前搜索路徑,使用下面的命令:
SHOW search_path;
在默認(rèn)設(shè)置下這將返回:
search_path
--------------
"$user", public
第一個(gè)元素說明一個(gè)和當(dāng)前用戶同名的模式會(huì)被搜索。如果不存在這個(gè)模式,該項(xiàng)將被忽略。第二個(gè)元素指向我們已經(jīng)見過的公共模式。
搜索路徑中的第一個(gè)模式是創(chuàng)建新對(duì)象的默認(rèn)存儲(chǔ)位置。這就是默認(rèn)情況下對(duì)象會(huì)被創(chuàng)建在公共模式中的原因。當(dāng)對(duì)象在任何其他沒有模式限定的環(huán)境中被引用(表修改、數(shù)據(jù)修改或查詢命令)時(shí),搜索路徑將被遍歷直到一個(gè)匹配對(duì)象被找到。因此,在默認(rèn)配置中,任何非限定訪問將只能指向公共模式。
要把新模式放在搜索路徑中,我們可以使用:
SET search_path TO myschema,public;
(我們?cè)谶@里省略了$user
,因?yàn)槲覀儾⒉涣⒓葱枰H缓笪覀兛梢詣h除該表而無需使用方案進(jìn)行限定:
DROP TABLE mytable;
同樣,由于myschema
是路徑中的第一個(gè)元素,新對(duì)象會(huì)被默認(rèn)創(chuàng)建在其中。
我們也可以這樣寫:
SET search_path TO myschema;
這樣我們?cè)跊]有顯式限定時(shí)再也不必去訪問公共模式了。公共模式?jīng)]有什么特別之處,它只是默認(rèn)存在而已,它也可以被刪除。
其他操作模式搜索路徑的方法請(qǐng)見第 9.26 節(jié)。
搜索路徑對(duì)于數(shù)據(jù)類型名稱、函數(shù)名稱和操作符名稱的作用與表名一樣。數(shù)據(jù)類型和函數(shù)名稱可以使用和表名完全相同的限定方式。如果我們需要在一個(gè)表達(dá)式中寫一個(gè)限定的操作符名稱,我們必須寫成一種特殊的形式:
OPERATOR(
schema
.
operator
)
這是為了避免句法歧義。例如:
SELECT 3 OPERATOR(pg_catalog.+) 4;
實(shí)際上我們通常都會(huì)依賴于搜索路徑來查找操作符,因此沒有必要去寫如此“丑陋”的東西。
默認(rèn)情況下,用戶不能訪問不屬于他們的方案中的任何對(duì)象。要允許這種行為,模式的擁有者必須在該模式上授予USAGE
權(quán)限。為了允許用戶使用方案中的對(duì)象,可能還需要根據(jù)對(duì)象授予額外的權(quán)限。
一個(gè)用戶也可以被允許在其他某人的模式中創(chuàng)建對(duì)象。要允許這種行為,模式上的CREATE
權(quán)限必須被授予。注意在默認(rèn)情況下,所有人都擁有在public
模式上的CREATE
和USAGE
權(quán)限。這使得用戶能夠連接到一個(gè)給定數(shù)據(jù)庫并在它的public
模式中創(chuàng)建對(duì)象?;厥者@一特權(quán)的 “5.9.6. 使用模式“調(diào)用:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
(第一個(gè)“public”是方案,第二個(gè)“public”指的是“每一個(gè)用戶”。第一種是一個(gè)標(biāo)識(shí)符,第二種是一個(gè)關(guān)鍵詞,所以兩者的大小寫不同。請(qǐng)回想第 4.1.1 標(biāo)識(shí)符和關(guān)鍵詞節(jié)中的指導(dǎo)方針。)
除public
和用戶創(chuàng)建的模式之外,每一個(gè)數(shù)據(jù)庫還包括一個(gè)pg_catalog
模式,它包含了系統(tǒng)表和所有內(nèi)建的數(shù)據(jù)類型、函數(shù)以及操作符。pg_catalog
總是搜索路徑的一個(gè)有效部分。如果沒有在路徑中顯式地包括該模式,它將在路徑中的模式之前被搜索。這保證了內(nèi)建的名稱總是能被找到。然而,如果我們希望用用戶定義的名稱重載內(nèi)建的名稱,可以顯式的將pg_catalog
放在搜索路徑的末尾。
由于系統(tǒng)表名稱以pg_
開頭,最好還是避免使用這樣的名稱,以避免和未來新版本中
可能出現(xiàn)的系統(tǒng)表名發(fā)生沖突。系統(tǒng)表將繼續(xù)采用以pg_
開頭的方式,這樣它們不會(huì)
與非限制的用戶表名稱沖突。
模式能夠以多種方式組織數(shù)據(jù).secure schema usage pattern防止不受信任的用戶更改其他用戶查詢的行為。
當(dāng)數(shù)據(jù)庫不使用安全模式使用方式時(shí),希望安全地查詢?cè)摂?shù)據(jù)庫的用戶將在每個(gè)會(huì)話開始時(shí)采取保護(hù)操作。
具體的說,他們將通過設(shè)置search_path
到空字符串或在其它情況下從search_path
中刪除非超級(jí)用戶可寫的模式來開始每個(gè)會(huì)話。
默認(rèn)配置可以很容易的支持一些使用模式。
將普通用戶約束在其私有的方案中。要實(shí)現(xiàn)這一點(diǎn),發(fā)出REVOKE CREATE ON SCHEMA public FROM PUBLIC
,并且為每一個(gè)用戶創(chuàng)建一個(gè)用其用戶名命名的方案。
回想一下以$user
開頭的默認(rèn)搜索路徑,該路徑解析為用戶名。
因此,如果每個(gè)用戶都有單獨(dú)的模式,則默認(rèn)情況下他們?cè)L問自己的模式。
在不受信任的用戶已經(jīng)登錄的數(shù)據(jù)庫中采用此模式后,請(qǐng)考慮審計(jì)名字類似于模式pg_catalog
中的對(duì)象的公共模式。
此方式是一種安全模式的使用方式,除非不受信任的用戶是數(shù)據(jù)庫所有者或擁有CREATEROLE
權(quán)限,在這種情況下沒有安全模式使用方式存在。
從默認(rèn)搜索路徑中刪除公共模式,通過修改postgresql.conf
或通過發(fā)出ALTER ROLE ALL SET search_path ="$user"
。
每一個(gè)都保留在公共模式中創(chuàng)建對(duì)象的能力,但是只有符合資格的名稱才會(huì)選擇這些對(duì)象。
雖然符合資格的表引用是可以的,但是要調(diào)用公共模式中的函數(shù)will be unsafe or unreliable。
如果在公共模式中創(chuàng)建函數(shù)或擴(kuò)展,請(qǐng)改用第一個(gè)方式。
否則,與第一個(gè)模式一樣,這是安全的,除非不受信任的用戶是數(shù)據(jù)庫所有者或擁有CREATEROLE
權(quán)限。
保持默認(rèn)。所有用戶都隱式地訪問公共模式。這模擬了方案根本不可用的情況,可以用于從無模式感知的世界平滑過渡。 但是,這絕不是一個(gè)安全的模式。只有當(dāng)數(shù)據(jù)庫僅有單個(gè)用戶或者少數(shù)相互信任的用戶時(shí),才可以接受。
對(duì)于任何一種模式,為了安裝共享的應(yīng)用(所有人都要用其中的表,第三方提供的額外函數(shù),等等),可把它們放在單獨(dú)的方案中。記住授予適當(dāng)?shù)奶貦?quán)以允許其他用戶訪問它們。然后用戶可以通過以方案名限定名稱的方式來引用這些額外的對(duì)象,或者他們可以把額外的方案放在自己的搜索路徑中。
在SQL標(biāo)準(zhǔn)中,在由不同用戶擁有的同一個(gè)模式中的對(duì)象是不存在的。此外,某些實(shí)現(xiàn)不允許創(chuàng)建與擁有者名稱不同名的模式。事實(shí)上,在那些僅實(shí)現(xiàn)了標(biāo)準(zhǔn)中基本模式支持的數(shù)據(jù)庫中,模式和用戶的概念是等同的。因此,很多用戶認(rèn)為限定名稱實(shí)際上是由
組成的。如果我們?yōu)槊恳粋€(gè)用戶都創(chuàng)建了一個(gè)模式,PostgreSQL實(shí)際也是這樣認(rèn)為的。
user_name
.table_name
同樣,在SQL標(biāo)準(zhǔn)中也沒有public
模式的概念。為了最大限度的與標(biāo)準(zhǔn)一致,我們不應(yīng)使用(甚至是刪除)public
模式。
當(dāng)然,某些SQL數(shù)據(jù)庫系統(tǒng)可能根本沒有實(shí)現(xiàn)方案,或者提供允許跨數(shù)據(jù)庫訪問的名字空間。如果需要使用這樣一些系統(tǒng),最好不要使用方案。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: