日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

CREATE FUNCTION

CREATE FUNCTION用于定義一個新函數(shù)。

簡介

CREATE FUNCTION定義一個新函數(shù)。CREATE OR REPLACE FUNCTION將創(chuàng)建一個新函數(shù)或者替換一個現(xiàn)有的函數(shù)。要定義一個函數(shù),用戶必須具有該語言上的USAGE特權(quán)。

如果包括了一個模式名,那么該函數(shù)會被創(chuàng)建在指定的模式中。否則,它會被創(chuàng)建在當(dāng)前模式中。新函數(shù)的名稱不能匹配同一個模式中具有相同輸入?yún)?shù)類型的任何現(xiàn)有函數(shù)或過程。不過,不同參數(shù)類型的函數(shù)和過程能夠共享一個名字(這被稱作重載)。

要替換一個現(xiàn)有函數(shù)的當(dāng)前定義,可以使用CREATE OR REPLACE FUNCTION。但不能用這種方式更改函數(shù)的名稱或者參數(shù)類型(如果嘗試這樣做,實際上就會創(chuàng)建一個新的不同的函數(shù))。還有,CREATE OR REPLACE FUNCTION將不會讓你更改一個現(xiàn)有函數(shù)的返回類型。要這樣做,你必須先刪除再重建該函數(shù)(在使用OUT參數(shù)時,這意味著除了刪除函數(shù)之外無法更改任何OUT參數(shù)的類型)。

當(dāng)CREATE OR REPLACE FUNCTION被用來替換一個現(xiàn)有的函數(shù),該函數(shù)的擁有權(quán)和權(quán)限不會改變。所有其他的函數(shù)屬性會按照該命令中所指定的或者隱含的來賦值。必須擁有(包括成為擁有角色的成員)該函數(shù)才能替換它。

如果你刪除并且重建一個函數(shù),新函數(shù)將和舊的不一樣,你將必須刪掉引用舊函數(shù)的現(xiàn)有規(guī)則、視圖、觸發(fā)器等。使用CREATE OR REPLACE FUNCTION更改一個函數(shù)定義不會破壞引用該函數(shù)的對象。還有,ALTER FUNCTION可以被用來更改一個現(xiàn)有函數(shù)的大部分輔助屬性。

創(chuàng)建該函數(shù)的用戶將成為該函數(shù)的擁有者。

要創(chuàng)建一個函數(shù),你必須擁有參數(shù)類型和返回類型上的USAGE特權(quán)。

語法

    CREATE [ OR REPLACE ] FUNCTION
        name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
        [ RETURNS rettype
          | RETURNS TABLE ( column_name column_type [, ...] ) ]
      { LANGUAGE lang_name
        | TRANSFORM { FOR TYPE type_name } [, ... ]
        | WINDOW
        | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
        | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
        | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
        | PARALLEL { UNSAFE | RESTRICTED | SAFE }
        | COST execution_cost
        | ROWS result_rows
        | SUPPORT support_function
        | SET configuration_parameter { TO value | = value | FROM CURRENT }
        | AS 'definition'
        | AS 'obj_file', 'link_symbol'
      } ...

參數(shù)

name要創(chuàng)建的函數(shù)的名稱(可以被模式限定)。

argmode一個參數(shù)的模式:INOUTINOUT或者VARIADIC。如果省略,默認(rèn)為IN。只有OUT參數(shù)能跟在一個VARIADIC參數(shù)后面。還有,OUTINOUT參數(shù)不能和RETURNS TABLE符號一起使用。

argname一個參數(shù)的名稱。一些語言(包括 SQL 和 PL/pgSQL)讓你在函數(shù)體中使用該名稱。對于其他語言,一個輸入?yún)?shù)的名字只是額外的文字(就該函數(shù)本身所關(guān)心的來說)。但是你可以在調(diào)用一個函數(shù)時使用輸入?yún)?shù)名來提高可讀性。在任何情況下,輸出參數(shù)的名稱是有意義的,因為它定義了結(jié)果行類型中的列名(如果忽略一個輸出參數(shù)的名稱,系統(tǒng)將選擇一個默認(rèn)的列名)。

argtype該函數(shù)參數(shù)(如果有)的數(shù)據(jù)類型(可以是模式限定的)。參數(shù)類型可以是基本類型、組合類型或者域類型,或者可以引用一個表列的類型。

根據(jù)實現(xiàn)語言,也可以允許指定cstring之類的“偽類型”。偽類型表示實際參數(shù)類型沒有被完整指定或者不屬于普通 SQL 數(shù)據(jù)類型集合。

可以寫 table_name . column_name %TYPE來引用一列的類型。使用這種特性有時可以幫助創(chuàng)建一個不受表定義更改影響的函數(shù)。

default_expr如果參數(shù)沒有被指定值時要用作默認(rèn)值的表達(dá)式。該表達(dá)式必須能被強(qiáng)制為該參數(shù)的參數(shù)類型。只有輸入(包括INOUT)參數(shù)可以具有默認(rèn)值。所有跟隨在一個具有默認(rèn)值的參數(shù)之后的輸入?yún)?shù)也必須有默認(rèn)值。

rettype返回數(shù)據(jù)類型(可能被模式限定)。返回類型可以是一種基本類型、組合類型或者域類型,也可以引用一個表列的類型。根據(jù)實現(xiàn)語言,也可以允許指定cstring之類的“偽類型”。如果該函數(shù)不會返回一個值,可以指定返回類型為void

當(dāng)有OUT或者INOUT參數(shù)時,可以省略RETURNS子句。如果存在,該子句必須和輸出參數(shù)所表示的結(jié)果類型一致:如果有多個輸出參數(shù),則為RECORD,否則與單個輸出參數(shù)的類型相同。

SETOF修飾符表示該函數(shù)將返回一個項的集合而不是一個單一項。

可以寫 table_name . column_name %TYPE來引用一列的類型。

column_nameRETURNS TABLE語法中一個輸出列的名稱。這實際上是另一種聲明OUT參數(shù)的方法,不過RETURNS TABLE也隱含了RETURNS SETOF

column_typeRETURNS TABLE語法中的輸出列的數(shù)據(jù)類型。

lang_name用以實現(xiàn)該函數(shù)的語言的名稱。可以是sqlcinternal或者一個用戶定義的過程語言的名稱,例如plpgsql。不推薦用單引號包圍該名稱,并且要求區(qū)分大小寫。

TRANSFORM {{ FOR TYPE type_name } [, ... ] }一個由轉(zhuǎn)換構(gòu)成的列表,對該函數(shù)的調(diào)用適用于它們。轉(zhuǎn)換在 SQL 類型和語言相關(guān)的數(shù)據(jù)類型之間進(jìn)行變換,詳見 CREATE TRANSFORM。過程語言實現(xiàn)通常把有關(guān)內(nèi)建類型的知識硬編碼在代碼中,因此那些不需要列舉在這里。如果一種過程語言實現(xiàn)不知道如何處理一種類型并且沒有轉(zhuǎn)換被提供,它將回退到一種默認(rèn)的行為來轉(zhuǎn)換數(shù)據(jù)類型,但是這取決于具體實現(xiàn)。

WINDOWWINDOW表示該函數(shù)是一個窗口函數(shù)而不是一個普通函數(shù)。當(dāng)前只用于用 C 編寫的函數(shù)。在替換一個現(xiàn)有函數(shù)定義時,不能更改WINDOW屬性。

IMMUTABLESTABLEVOLATILE這些屬性告知查詢優(yōu)化器該函數(shù)的行為。最多只能指定其中一個。如果這些都不出現(xiàn),則會默認(rèn)為VOLATILE

IMMUTABLE表示該函數(shù)不能修改數(shù)據(jù)庫并且對于給定的參數(shù)值總是會返回相同的值。也就是說,它不會做數(shù)據(jù)庫查找或者使用沒有在其參數(shù)列表中直接出現(xiàn)的信息。如果給定合格選項,任何用全常量參數(shù)對該函數(shù)的額調(diào)用可以立刻用該函數(shù)值替換。

STABLE表示該函數(shù)不能修改數(shù)據(jù)庫,并且對于相同的參數(shù)值,它在一次表掃描中將返回相同的結(jié)果。但是這種結(jié)果在不同的 SQL 語句執(zhí)行期間可能會變化。對于那些結(jié)果依賴于數(shù)據(jù)庫查找、參數(shù)變量(例如當(dāng)前時區(qū))等的函數(shù)來說,這是合適的(對希望查詢被當(dāng)前命令修改的行的AFTER觸發(fā)器不適合)。還要注意current_timestamp函數(shù)族適合被標(biāo)記為穩(wěn)定,因為它們的值在一個事務(wù)內(nèi)不會改變。

VOLATILE表示該函數(shù)的值在一次表掃描中都有可能改變,因此不能做優(yōu)化。在這種意義上,相對較少的數(shù)據(jù)庫函數(shù)是不穩(wěn)定的,一些例子是random()currval()timeofday()。但是注意任何有副作用的函數(shù)都必須被分類為不穩(wěn)定的,即便其結(jié)果是可以預(yù)測的,這是為了調(diào)用被優(yōu)化掉。一個例子是setval()

LEAKPROOFLEAKPROOF表示該函數(shù)沒有副作用。它不會泄露有關(guān)其參數(shù)的信息(除了通過返回值)。例如,一個只對某些參數(shù)值拋出錯誤消息而對另外一些卻不拋出錯誤的函數(shù)不是防泄漏的,一個把參數(shù)值包括在任何錯誤消息中的函數(shù)也不是防泄漏的。這會影響系統(tǒng)如何執(zhí)行在使用security_barrier選項創(chuàng)建的視圖或者開啟了行級安全性的表上執(zhí)行查詢。對于包含有非防泄漏函數(shù)的查詢,系統(tǒng)將在任何來自查詢本身的用戶提供條件之前強(qiáng)制來自安全策略或者安全屏障的條件,防止無意中的數(shù)據(jù)暴露。被標(biāo)記為防泄漏的函數(shù)和操作符被假定是可信的,并且可以在安全性策略和安全性屏障視圖的條件之前被執(zhí)行。此外,沒有參數(shù)的函數(shù)或者不從安全屏障視圖或表傳遞任何參數(shù)的函數(shù)不一定要被標(biāo)記為防泄漏的。

CALLED ON NULL INPUTRETURNS NULL ON NULL INPUTSTRICTCALLED ON NULL INPUT(默認(rèn))表示在某些參數(shù)為空值時應(yīng)正常調(diào)用該函數(shù)。如果有必要,函數(shù)的作者應(yīng)該負(fù)責(zé)檢查空值并且做出適當(dāng)?shù)南鄳?yīng)。

RETURNS NULL ON NULL INPUTSTRICT表示只要其任意參數(shù)為空值,該函數(shù)就會返回空值。如果指定了這個參數(shù),當(dāng)有空值參數(shù)時該函數(shù)不會被執(zhí)行,而是自動返回一個空值結(jié)果。

[EXTERNAL] SECURITY INVOKER[EXTERNAL] SECURITY DEFINERSECURITY INVOKER表示要用調(diào)用該函數(shù)的用戶的特權(quán)來執(zhí)行它。這是默認(rèn)值。SECURITY DEFINER指定要用擁有該函數(shù)的用戶的特權(quán)來執(zhí)行該函數(shù)。

為了符合 SQL,允許使用關(guān)鍵詞EXTERNAL。但是它是可選的,因為與 SQL 中不同,這個特性適用于所有函數(shù)而不僅是那些外部函數(shù)。

PARALLELPARALLEL UNSAFE表示該函數(shù)不能在并行模式中運行并且 SQL 語句中存在一個這樣的函數(shù)會強(qiáng)制使用順序執(zhí)行計劃。這是默認(rèn)選項。PARALLEL RESTRICTED表示該函數(shù)能在并行模式中運行,但是其執(zhí)行被限制在并行組的領(lǐng)導(dǎo)者中。PARALLEL SAFE表示該函數(shù)對于在并行模式中運行是安全的并且不受限制。

如果函數(shù)修改任何數(shù)據(jù)庫狀態(tài)、會使用子事務(wù)之類的方式改變事務(wù)、訪問序列或者對設(shè)置(如setval)做出持久性的更改,它們就應(yīng)該被標(biāo)記為并行不安全。如果它們訪問臨時表、客戶端連接狀態(tài)、游標(biāo)、預(yù)備語句或者系統(tǒng)無法在并行模式中同步的本地后端狀態(tài)(例如setseed只能在組領(lǐng)導(dǎo)者中執(zhí)行,因為另一個進(jìn)程所作的更改不會在領(lǐng)導(dǎo)者中被反映出來),它們應(yīng)該被標(biāo)為并行受限。通常,如果一個函數(shù)是受限的或者不安全的卻被標(biāo)成了安全,或者它本來是不安全的卻被標(biāo)成了受限,在并行查詢中執(zhí)行時它可能會拋出錯誤或者產(chǎn)生錯誤的答案。如果被錯誤的標(biāo)記, C 語言函數(shù)理論上可能展現(xiàn)出完全無法定義的行為,因為系統(tǒng)沒有辦法保護(hù)自己不受任意的 C 代碼影響,但是在大部分情況下其結(jié)果也不會比任何其他函數(shù)差到哪里去。如果有疑問,函數(shù)應(yīng)該被標(biāo)為UNSAFE,這也是默認(rèn)值。

COST execution_cost一個給出該函數(shù)的估計執(zhí)行代價的正數(shù),單位是 cpu_operator_cost。如果該函數(shù)返回一個集合,這就是每個被返回行的代價。如果沒有指定代價,對 C 語言和內(nèi)部函數(shù)會指定為 1 個單位,對其他語言的函數(shù)則會指定為 100 單位。更大的值會導(dǎo)致規(guī)劃器嘗試避免對該函數(shù)的不必要的過多計算。

ROWS result_rows一個正數(shù),它給出規(guī)劃器期望該函數(shù)返回的行數(shù)估計。只有當(dāng)該函數(shù)被聲明為返回一個集合時才允許這個參數(shù)。默認(rèn)假設(shè)為 1000 行。

SUPPORT support_function用于此函數(shù)的planner support function的名稱(可選的模式限定)。你必須是超級用戶才能使用此選項。

configuration_parameter valueSET子句導(dǎo)致進(jìn)入該函數(shù)時指定配置參數(shù)將被設(shè)置為指定值。并且在該函數(shù)退出時恢復(fù)到該參數(shù)之前的值。SET FROM CURRENT會把CREATE FUNCTION被執(zhí)行時該參數(shù)的當(dāng)前值保存為進(jìn)入該函數(shù)時將被應(yīng)用的值。

如果一個SET子句被附加到一個函數(shù),那么在該函數(shù)內(nèi)為同一個變量執(zhí)行的SET LOCAL命令會被限制于該函數(shù):在函數(shù)退出時該配置參數(shù)之前的值仍會被恢復(fù)。不過,一個普通的SET命令(沒有LOCAL)會覆蓋SET子句,更像一個之前的SET LOCAL命令所做的那樣:這種命令的效果在函數(shù)退出后將會持續(xù),除非當(dāng)前事務(wù)被回滾。

definition一個定義該函數(shù)的字符串常量,其含義取決于語言。它可以是一個內(nèi)部函數(shù)名、一個對象文件的路徑、一個 SQL 命令或者用一種過程語言編寫的文本。

obj_file , link_symbol當(dāng) C 語言源代碼中該函數(shù)的名稱與 SQL 函數(shù)的名稱不同時,這種形式的AS子句被用于動態(tài)可載入 C 語言函數(shù)。字符串 obj_file是包含編譯好的 C 函數(shù)的動態(tài)庫文件的名稱,它會由 LOAD 命令解析。字符串 link_symbol是該函數(shù)的鏈接符號,也就是該函數(shù)在 C 語言源代碼中的名稱。如果省略鏈接符號,它將被假定為要定義的 SQL 函數(shù)的名稱。所有函數(shù)的 C 名稱都必須不同,因此必須為重載的 C 函數(shù)給出不同的 C 名稱(例如把參數(shù)類型作為 C 名稱的一部分)。

在重復(fù)調(diào)用引用同一對象文件的CREATE FUNCTION時,對每個會話該文件只會被載入一次。要卸載并且重新裝載該文件(可能是在開發(fā)期間),需要開始一個新會話。

重載

PolarDB允許函數(shù)重載,也就是說同一個名稱可以被用于多個不同的函數(shù),只要它們具有可區(qū)分的輸入?yún)?shù)類型。

如果兩個函數(shù)具有相同的名稱和輸入?yún)?shù)類型,它們被認(rèn)為相同(不考慮任何OUT參數(shù))。因此這些聲明會沖突:

    CREATE FUNCTION foo(int) ...
    CREATE FUNCTION foo(int, out text) ...

具有不同參數(shù)類型列表的函數(shù)在創(chuàng)建時將不會被認(rèn)為是沖突的,但是如果默認(rèn)值被提供,在使用時它們有可能會沖突。例如,考慮

    CREATE FUNCTION foo(int) ...
    CREATE FUNCTION foo(int, int default 42) ...

調(diào)用foo(10)將會失敗,因為在要決定應(yīng)該調(diào)用哪個函數(shù)時會有歧義。

說明

允許把完整的 SQL 類型語法用于聲明一個函數(shù)的參數(shù)和返回值。不過,CREATE FUNCTION會拋棄帶圓括號的類型修飾符(例如類型numeric的精度域)。例如CREATE FUNCTION foo (varchar(10)) ...CREATE FUNCTION foo (varchar) ...完全一樣。

在用CREATE OR REPLACE FUNCTION替換一個現(xiàn)有函數(shù)時,對于更改參數(shù)名是有限制的。不能更改已經(jīng)分配給任何輸入?yún)?shù)的名稱(不過可以給之前沒有名稱的參數(shù)增加名稱)。如果有多于一個輸出參數(shù),不能更改輸出參數(shù)的名稱,因為可能會改變描述函數(shù)結(jié)果的匿名組合類型的列名。這些限制是為了確保函數(shù)被替換時,已有的對該函數(shù)的調(diào)用不會停止工作。

如果一個被聲明為STRICT的函數(shù)帶有一個VARIADIC參數(shù),會嚴(yán)格檢查該可變數(shù)組作為一個整體是否為非空。如果該數(shù)組有空值元素,該函數(shù)仍將被調(diào)用。

示例

這里是一些小例子,它們可以幫你了解函數(shù)創(chuàng)建。

    CREATE FUNCTION add(integer, integer) RETURNS integer
        AS 'select $1 + $2;'
        LANGUAGE SQL
        IMMUTABLE
        RETURNS NULL ON NULL INPUT;

在PL/pgSQL中,使用一個參數(shù)名稱增加一個整數(shù):

    CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
            BEGIN
                    RETURN i + 1;
            END;
    $$ LANGUAGE plpgsql;

返回一個包含多個輸出參數(shù)的記錄:

    CREATE FUNCTION dup(in int, out f1 int, out f2 text)
        AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
        LANGUAGE SQL;

    SELECT * FROM dup(42);

你可以用更復(fù)雜的方式(用一個顯式命名的組合類型)來做同樣的事情:

    CREATE TYPE dup_result AS (f1 int, f2 text);

    CREATE FUNCTION dup(int) RETURNS dup_result
        AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
        LANGUAGE SQL;

    SELECT * FROM dup(42);

另一種返回多列的方法是使用一個TABLE函數(shù):

    CREATE FUNCTION dup(int) RETURNS TABLE(f1 int, f2 text)
        AS $$ SELECT $1, CAST($1 AS text) || ' is text' $$
        LANGUAGE SQL;

    SELECT * FROM dup(42);

不過,TABLE函數(shù)與之前的例子不同,因為它實際返回了一個記錄集合而不只是一個記錄。

安全地編寫 SECURITY DEFINER函數(shù)

因為一個SECURITY DEFINER函數(shù)會被以創(chuàng)建它的用戶的特權(quán)來執(zhí)行,需要小心地確保該函數(shù)不會被誤用。為了安全,search_path 應(yīng)該被設(shè)置為排除任何不可信用戶可寫的模式。這可以阻止惡意用戶創(chuàng)建對象(例如表、函數(shù)以及操作符)來掩飾該函數(shù)所要用到的對象。在這方面特別重要的是臨時表模式,默認(rèn)情況下它會第一個被搜索并且通常對任何用戶都是可寫的。可以通過強(qiáng)制最后搜索臨時模式來得到一種安全的布局。要這樣做,把pg_temp寫成search_path中的最后一項。這個函數(shù)展示了安全的用法:

    CREATE FUNCTION check_password(uname TEXT, pass TEXT)
    RETURNS BOOLEAN AS $$
    DECLARE passed BOOLEAN;
    BEGIN
            SELECT  (pwd = $2) INTO passed
            FROM    pwds
            WHERE   username = $1;

            RETURN passed;
    END;
    $$  LANGUAGE plpgsql
        SECURITY DEFINER
        -- 設(shè)置一個安全的 search_path:受信的模式,然后是 'pg_temp'。
        SET search_path = admin, pg_temp;

這個函數(shù)的目的是為了訪問表admin.pwds。但是如果沒有SET子句或者帶有SET子句卻只提到admin,該函數(shù)會變成創(chuàng)建一個名為pwds的臨時表。

默認(rèn)情況下,會為新創(chuàng)建的函數(shù)給PUBLIC授予執(zhí)行特權(quán)。你常常會希望把安全定義器函數(shù)的使用限制在某些用戶中。要這樣做,你必須收回默認(rèn)的PUBLIC特權(quán),然后選擇性地授予執(zhí)行特權(quán)。為了避免出現(xiàn)新函數(shù)能被所有人訪問的時間窗口,應(yīng)在一個事務(wù)中創(chuàng)建它并且設(shè)置特權(quán)。例如:

    BEGIN;
    CREATE FUNCTION check_password(uname TEXT, pass TEXT) ... SECURITY DEFINER;
    REVOKE ALL ON FUNCTION check_password(uname TEXT, pass TEXT) FROM PUBLIC;
    GRANT EXECUTE ON FUNCTION check_password(uname TEXT, pass TEXT) TO admins;
    COMMIT;