

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# `CREATE FUNCTION`
<a name="create-function-syntax-support"></a>

`CREATE FUNCTION` 會定義新的 函數。

**重要**  
在 Amazon Aurora DSQL 中， `CREATE FUNCTION`僅支援 SQL 語言函數 (`LANGUAGE sql`)。

## 支援的語法
<a name="create-function-supported-syntax"></a>

```
CREATE [ OR REPLACE ] FUNCTION
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
    [ RETURNS rettype
      | RETURNS TABLE ( column_name column_type [, ...] ) ]
  { LANGUAGE sql
    | { IMMUTABLE | STABLE | VOLATILE }
    | { 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
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | RETURN expression
    | BEGIN ATOMIC statement; [ statement; ... ] END
  } ...

where LANGUAGE must be sql
```

## 說明
<a name="create-function-description"></a>

`CREATE FUNCTION` 會定義新函數。 `CREATE OR REPLACE FUNCTION`會建立新的函數，或取代現有的定義。若要能夠定義函數，您必須在語言上具有 `USAGE`權限。

如果包含結構描述名稱，則會在指定的結構描述中建立函數。否則，函數會在目前結構描述中建立。新函數的名稱不得與相同結構描述中具有相同輸入引數類型的任何現有函數相符。不過，不同引數類型的函數可以共用名稱 （稱為*過載*)。

若要取代現有函數的目前定義，請使用 `CREATE OR REPLACE FUNCTION`。您無法以這種方式變更函數的名稱或引數類型 （這實際上會建立新的不同函數）。此外，您無法使用 `CREATE OR REPLACE FUNCTION` 變更現有函數的傳回類型。若要這樣做，您必須捨棄並重新建立函數。

當 `CREATE OR REPLACE FUNCTION` 用來取代現有函數時，函數的擁有權和許可不會變更。所有其他函數屬性都會指派命令中指定或隱含的值。您必須擁有 函數才能取代它 （這包括成為擁有角色的成員）。

如果您捨棄並重新建立函數，則新函數與舊函數的實體不同；您必須捨棄參考舊函數的現有規則、檢視等。使用 `CREATE OR REPLACE FUNCTION`變更函數定義，而不會破壞參考函數的物件。

您成為所建立函數的擁有者。

若要能夠建立函數，您必須具有引數類型和傳回類型的`USAGE`權限。

`SQL` 函數會將一或多個`SQL`陳述式包裝成可重複使用、可呼叫的單位。使用 函數來集中常用表達式或計算、跨多個查詢套用一致的邏輯，並透過呼叫單一 函數來簡化應用程式程式碼，而不是重複相同的 `SQL`。

## Parameters
<a name="create-function-parameters"></a>

**{{name}}**  
要建立之函數的名稱 （選擇性符合結構描述資格）。

**{{argmode}}**  
引數的模式：`IN`、`INOUT`、 `OUT`或 `VARIADIC`。如果省略，預設值為 `IN`。 `VARIADIC` 必須是最後一個輸入參數；只有`OUT`引數可以跟隨它。 `OUT`和 `INOUT`引數無法與`RETURNS TABLE`符號結合。

**{{argname}}**  
引數的名稱。在 SQL 函數中，您可以在函數內文中依名稱參考引數。`OUT` 或 `INOUT`引數的名稱也很重要，因為它在結果資料列類型中定義對應的資料欄名稱。

**{{argtype}}**  
引數的資料類型。這可以是任何 Aurora DSQL 支援的基本類型、陣列類型或網域。如需詳細資訊，請參閱[Aurora DSQL 支援的資料類型](working-with-postgresql-compatibility-supported-data-types.md)。您也可以使用 `%TYPE` 表示法來參考現有資料表欄的類型。

**{{default\_expr}}**  
若未指定引數，則用作預設值的表達式。表達式必須可強制參數的引數類型。只有 `IN`和 `INOUT`引數可以有預設值。具有預設值的每個引數後面也必須有一個預設值。

**{{重試類型}}**  
傳回資料類型。這可以是任何 Aurora DSQL 支援的基本類型、陣列類型或網域。如需詳細資訊，請參閱[Aurora DSQL 支援的資料類型](working-with-postgresql-compatibility-supported-data-types.md)。若要傳回一組資料列，請使用 `SETOF {{rettype}}`或 `RETURNS TABLE`。如果函數不應傳回值，請指定 `void`作為傳回類型。有 `OUT`或 `INOUT` 參數時，可以省略 `RETURNS`子句，而 函數會傳回 `record`或對應的資料列類型。

**`RETURNS TABLE ( {{column_name}} {{column_type}} [, ...] )`**  
指定 函數會傳回一組列，其中包含具名資料欄及其類型。這相當於宣告一或多個`OUT`參數，並指定 `SETOF`作為傳回類型。

**`LANGUAGE sql`**  
用於實作 函數的語言。在 Aurora DSQL 中，這必須是 `sql`。如果您省略 `LANGUAGE`子句並提供 `BEGIN ATOMIC`或 `RETURN`內文，`sql`則會假設 。字串常數內文 (`AS '{{definition}}'`) 需要明確`LANGUAGE sql`子句；省略它失敗並顯示錯誤 `no language specified`。

**`IMMUTABLE` / `STABLE` / `VOLATILE`**  
這些屬性會通知查詢最佳化工具有關 函數的行為。您最多可以指定一個。如果您省略這三個，函數會預設為 `VOLATILE`。  
+ `IMMUTABLE` 表示函數無法修改資料庫，並在指定相同的引數值時一律傳回相同的結果。
+ `STABLE` 表示函數無法修改資料庫。在單一資料表掃描中，它會持續傳回相同引數值的相同結果，但結果可能會在 SQL 陳述式之間變更。
+ `VOLATILE` 表示即使在單一資料表掃描內，函數值也可以變更，因此無法進行最佳化。

**`CALLED ON NULL INPUT` / `RETURNS NULL ON NULL INPUT` / `STRICT`**  
`CALLED ON NULL INPUT` （預設值） 表示函數在部分引數為 Null 時正常呼叫。 `RETURNS NULL ON NULL INPUT`或 `STRICT` 表示函數在其任何引數為 Null 時一律傳回 Null。如果指定，Aurora DSQL 不會在任何引數為 null 時執行函數；而是自動傳回 null。

**`[ EXTERNAL ] SECURITY INVOKER` / `[ EXTERNAL ] SECURITY DEFINER`**  
`SECURITY INVOKER` （預設值） 表示要使用呼叫該函數之使用者的權限來執行該函數。 `SECURITY DEFINER` 指定要使用擁有該函數之使用者的權限來執行該函數。允許 SQL 一致性`EXTERNAL`的關鍵字，但這是選用的。

**`PARALLEL { UNSAFE | RESTRICTED | SAFE }`**  
Aurora DSQL 接受並存放`PARALLEL`標記。不過，此標記不會影響查詢執行。

**`COST {{execution_cost}}`**  
正數，提供函數的預估執行成本。如果函數傳回集合，則此值是每個傳回資料列的預估成本。當查詢規劃器未內嵌函數時，會使用此預估值。

**`ROWS {{result_rows}}`**  
正數，表示查詢規劃器預期函數傳回的預估資料列數。只有在宣告函數傳回集合時，才允許這麼做。預設假設為 1000 個資料列。

**`SET {{configuration_parameter}} { TO {{value}} | = {{value}} | FROM CURRENT }`**  
`SET` 子句會在輸入函數時將指定的組態參數設定為指定的值，然後在函數結束時還原為先前的值。 會`SET FROM CURRENT`儲存當 執行`CREATE FUNCTION`時為目前參數的值，做為輸入函數時要套用的值。

**`AS '{{definition}}'`**  
定義函數的字串常數；意義取決於語言。對於 SQL 語言函數，它是構成函數內文的 SQL 陳述式。

**`RETURN {{expression}}`**  
使用傳回單一表達式之函數的 SQL 標準語法來定義函數內文。這是字串常數表單的替代方案。

**`BEGIN ATOMIC {{statement}}; [ ... ] END`**  
使用 SQL 標準語法定義函數內文。內文包含一或多個 SQL 陳述式。此表單僅適用於 `LANGUAGE sql`。原子主體中的陳述式會追蹤為函數的相依性。例如，如果沒有同時捨棄函數或使用 ，則無法捨棄內文中參考的資料表`DROP ... CASCADE`。

## 備註
<a name="create-function-notes"></a>

使用 `DROP FUNCTION`陳述式移除 函數。您也可以使用 和 授予`GRANT`和撤銷函數的權限 `REVOKE`（例如 `REVOKE ALL ON FUNCTION`)。

讀取或修改資料表中資料的任何函數都會受到與對等 SQL 陳述式直接執行相同的交易和並行行為的影響。宣告`IMMUTABLE`或`STABLE`不得修改資料庫的函數。

若要更新現有函數的定義，請使用 `CREATE OR REPLACE FUNCTION`。您無法以這種方式變更函數的引數類型或傳回類型；而是捨棄並重新建立函數。

若要重新命名函數、變更其擁有者，或將其移至另一個結構描述，請使用 `ALTER FUNCTION`。若要變更任何其他屬性，請使用 `CREATE OR REPLACE FUNCTION`搭配所需的變更。如需詳細資訊，請參閱[`ALTER FUNCTION`](alter-function-syntax-support.md)。

支援函數過載：只要多個函數的輸入引數類型不同，您可以使用相同的名稱來定義多個函數。使用者定義的函數也可以呼叫其他 函數，並且可以陰影相同名稱和引數類型的內建函數。

對於傳回內文包含多個陳述式的集合 (`SETOF` 或 `RETURNS TABLE`) 的函數，只會傳回最終陳述式的結果。函數仍會執行較早的陳述式，但會捨棄其結果。這是 SQL 語言函數的標準行為。建構函數，使其最終陳述式產生完整的結果集。

集合傳回函數不保證任何特定的資料列順序。若要控制資料列順序，請在查詢中包含 `ORDER BY`子句。

## 考量事項
<a name="create-function-considerations"></a>

下列`CREATE FUNCTION`功能會傳回顯示的錯誤。

**`LEAKPROOF`**  
傳回錯誤 `only superuser can define a leakproof function`。 `NOT LEAKPROOF`（預設值） 被接受。

**`TRANSFORM FOR TYPE`**  
傳回錯誤 `transform for type {{type}} language "sql" does not exist`。

**`SUPPORT` （規劃器支援函數）**  
傳回錯誤 `function {{name}}(internal) does not exist`。

**使用者定義的複合類型 (`CREATE TYPE ... AS`)，包括傳回複合類型的函數**  
傳回錯誤 `unsupported statement: CompositeType`。

Aurora DSQL 不支援 `CREATE PROCEDURE`，失敗並顯示錯誤 `PROCEDURE is not supported`。

`WINDOW` 屬性在語法上被接受，但對 SQL 語言函數沒有用處。避免使用此屬性。

## 範例
<a name="create-function-examples"></a>

建立簡單的 SQL 函數，使用字串常數內文來新增兩個整數：

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

使用 SQL 標準`RETURN`內文和具名引數建立相同的函數：

```
CREATE FUNCTION add(a integer, b integer) RETURNS integer
    LANGUAGE sql
    IMMUTABLE
    RETURN a + b;
```

使用 `RETURNS TABLE`和內`BEGIN ATOMIC`文建立傳回一組資料列的函數：

```
CREATE FUNCTION employees_in_dept(dept_id integer)
    RETURNS TABLE (id integer, name text)
    LANGUAGE sql
    STABLE
    BEGIN ATOMIC
        SELECT id, name FROM employees WHERE department_id = dept_id;
    END;
```

建立以擁有者權限執行的 函數，並在呼叫期間設定組態參數：

```
CREATE FUNCTION current_department() RETURNS text
    LANGUAGE sql
    STABLE
    SECURITY DEFINER
    SET search_path = app
    AS 'SELECT current_setting(''app.department'');';
```

## 相容性
<a name="create-function-compatibility"></a>

`CREATE FUNCTION` 命令在 SQL 標準中定義。PostgreSQL 實作可以相容的方式使用，但有許多擴充功能。相反地，SQL 標準會指定許多未在 PostgreSQL 中實作的選用功能。

以下是重要的相容性問題：
+ `OR REPLACE` 是 PostgreSQL 擴充功能。
+ 為了與某些其他資料庫系統的相容性，可以在 {{argname 之前或之後寫入 argmode}}。 {{}}但只有第一種方式符合標準。
+ 對於參數預設值，SQL 標準僅指定具有`DEFAULT`關鍵字的語法。與 的語法`=`用於 T-SQL 和 Firebird。
+ `SETOF` 修飾詞是 PostgreSQL 延伸模組。
+ 只有 SQL 會標準化為語言。
+ 除了 `CALLED ON NULL INPUT`和 以外的所有其他屬性`RETURNS NULL ON NULL INPUT`不標準化。
+ 針對`LANGUAGE sql`函數內文，SQL 標準只會指定 {{sql\_body}} 格式。

簡單`LANGUAGE sql`函數的撰寫方式既符合標準，又可移植到其他實作。使用進階功能、最佳化屬性或其他語言的更複雜函數，對 PostgreSQL 來說一定是有意義的。