

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

`CREATE FUNCTION` define uma nova função.

**Importante**  
No Amazon Aurora DSQL, `CREATE FUNCTION` só comporta funções da linguagem SQL (`LANGUAGE sql`). 

## Sintaxe compatível
<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
```

## Descrição
<a name="create-function-description"></a>

`CREATE FUNCTION` define uma nova função. `CREATE OR REPLACE FUNCTION` criará uma função ou substituirá uma definição existente. Para poder definir uma função, é necessário ter o privilégio `USAGE` na linguagem.

Se um nome de esquema for incluído, a função será criada no esquema especificado. Caso contrário, a função será criada no esquema atual. O nome da nova função não deve corresponder a nenhuma função existente com os mesmos tipos de argumentos de entrada no mesmo esquema. No entanto, funções de diferentes tipos de argumentos podem compartilhar um nome (isso é chamado de *sobrecarga*).

Para substituir a definição atual de uma função existente, use `CREATE OR REPLACE FUNCTION`. Você não pode alterar o nome nem os tipos de argumento de uma função dessa forma (isso, na verdade, criaria uma função nova e distinta). Além disso, você não pode usar `CREATE OR REPLACE FUNCTION` para alterar o tipo de retorno de uma função existente. Para isso, é necessário descartar e recriar a função.

Quando `CREATE OR REPLACE FUNCTION` é usado para substituir uma função existente, a propriedade e as permissões da função não mudam. Todas as outras propriedades da função recebem os valores especificados ou implícitos no comando. Para substituir uma função, ela deve pertencer a você (isso inclui ser membro do perfil de propriedade). 

Se você descartar e depois recriar uma função, a nova função não será a mesma entidade da antiga; você terá que descartar as regras, visualizações etc. existentes, que se referem à função antiga. Use `CREATE OR REPLACE FUNCTION` para alterar a definição de uma função sem romper objetos que se refiram à função. 

Você se torna o proprietário de uma função que você criou.

Para poder criar uma função, você deve ter o privilégio `USAGE` sobre os tipos de argumentos e o tipo de retorno.

Uma função `SQL` agrupa uma ou mais instruções `SQL` em uma unidade reutilizável e chamável. Use funções para centralizar expressões ou cálculos comuns, aplicar lógica consistente em várias consultas e simplificar o código da aplicação chamando uma única função em vez de repetir o mesmo código `SQL`. 

## Parâmetros
<a name="create-function-parameters"></a>

**{{name}}**  
O nome (opcionalmente qualificado para o esquema) da função a ser criada.

**{{argmode}}**  
O modo de um argumento: `IN`, `OUT`, `INOUT` ou `VARIADIC`. Se for omitido, o padrão será `IN`. `VARIADIC` deve ser o último parâmetro de entrada; somente argumentos `OUT` podem segui-lo. Os argumentos `OUT` e `INOUT` não podem ser combinados com a notação `RETURNS TABLE`.

**{{argname}}**  
O nome de um argumento. Em uma função SQL, você pode se referir a um argumento pelo nome no corpo da função. O nome de um argumento `OUT` ou `INOUT` também é significativo, pois define o nome da coluna correspondente no tipo de linha de resultado.

**{{argtype}}**  
Tipo de dados de um argumento. Isso pode ser qualquer tipo básico, tipo de matriz ou domínio compatível com o Aurora DSQL. Para obter mais informações, consulte [Tipos de dados compatíveis no Aurora DSQL](working-with-postgresql-compatibility-supported-data-types.md). Você também pode fazer referência ao tipo de uma coluna de tabela existente usando a notação `%TYPE`.

**{{default\_expr}}**  
Uma expressão a ser usada como valor padrão se o argumento não for especificado. A expressão deve ser convertida no tipo de argumento do parâmetro. Somente os argumentos `IN` e `INOUT` podem ter um valor padrão. Todos os argumentos após um argumento com valor padrão também devem ter um valor padrão.

**{{rettype}}**  
O tipo de dados de retorno. Isso pode ser qualquer tipo básico, tipo de matriz ou domínio compatível com o Aurora DSQL. Para obter mais informações, consulte [Tipos de dados compatíveis no Aurora DSQL](working-with-postgresql-compatibility-supported-data-types.md). Para exibir um conjunto de linhas, use `SETOF {{rettype}}` ou `RETURNS TABLE`. Se a função não deve retornar um valor, especifique `void` como o tipo de retorno. Quando há parâmetros `OUT` ou `INOUT`, a cláusula `RETURNS` pode ser omitida e a função exibe um `record` ou o tipo de linha correspondente.

**`RETURNS TABLE ( {{column_name}} {{column_type}} [, ...] )`**  
Especifica que a função exiba um conjunto de linhas com as colunas nomeadas e seus tipos. Isso equivale a declarar um ou mais parâmetros `OUT` e especificar `SETOF` como o tipo de retorno.

**`LANGUAGE sql`**  
A linguagem usada para implementar a função. No Aurora DSQL, deve ser `sql`. Se você omitir a cláusula `LANGUAGE` e fornecer um corpo `BEGIN ATOMIC` ou `RETURN`, `sql` será considerado o padrão. Um corpo constante de string (`AS '{{definition}}'`) requer uma cláusula `LANGUAGE sql` explícita; omiti-la resulta no erro `no language specified`.

**`IMMUTABLE` / `STABLE` / `VOLATILE`**  
Esses atributos informam o otimizador de consulta sobre o comportamento da função. Você pode especificar no máximo um. Se você omitir todos os três, o padrão da função será `VOLATILE`.  
+ `IMMUTABLE` indica que a função não pode modificar o banco de dados e sempre exibe o mesmo resultado quando recebe os mesmos valores de argumento.
+ `STABLE` indica que a função não pode modificar o banco de dados. Em uma única verificação de tabela, ela exibe consistentemente o mesmo resultado para os mesmos valores de argumento, mas o resultado pode mudar nas instruções SQL.
+ `VOLATILE` indica que o valor da função pode mudar mesmo em uma única verificação de tabela, portanto, nenhuma otimização pode ser feita.

**`CALLED ON NULL INPUT` / `RETURNS NULL ON NULL INPUT` / `STRICT`**  
`CALLED ON NULL INPUT` (o padrão) indica que a função é chamada normalmente quando alguns de seus argumentos são nulos. `RETURNS NULL ON NULL INPUT` ou `STRICT` indica que a função sempre exibe nulo quando qualquer um de seus argumentos é nulo. Se especificado, o Aurora DSQL não executa a função quando qualquer argumento é nulo; em vez disso, a função exibe nulo automaticamente. 

**`[ EXTERNAL ] SECURITY INVOKER` / `[ EXTERNAL ] SECURITY DEFINER`**  
`SECURITY INVOKER` (o padrão) indica que a função deve ser executada com os privilégios do usuário que a chama. `SECURITY DEFINER` especifica que a função deve ser executada com os privilégios do usuário que a possui. A palavra-chave `EXTERNAL` é permitida para conformidade com SQL, mas é opcional.

**`PARALLEL { UNSAFE | RESTRICTED | SAFE }`**  
O Aurora DSQL aceita e armazena a marcação `PARALLEL`. No entanto, essa marcação não afeta a execução da consulta. 

**`COST {{execution_cost}}`**  
Um número positivo dando o custo de execução estimado para a função. Se a função exibir um conjunto, esse valor será o custo estimado por linha exibida. O planejador de consultas usa essa estimativa quando não incorpora a função.

**`ROWS {{result_rows}}`**  
Um número positivo que fornece o número estimado de linhas que o planejador de consultas deve esperar que a função exiba. Isso só é permitido quando a função é declarada para exibir um conjunto. A suposição padrão é mil linhas.

**`SET {{configuration_parameter}} { TO {{value}} | = {{value}} | FROM CURRENT }`**  
A cláusula `SET` faz com que o parâmetro de configuração especificado seja definido como o valor especificado quando a função é inserida e, depois, restaurado ao valor anterior quando a função é encerrada. `SET FROM CURRENT` salva o valor do parâmetro que é atual quando `CREATE FUNCTION` é executado como o valor a ser aplicado quando a função é inserida.

**`AS '{{definition}}'`**  
Uma constante de string definindo a função; o significado depende da linguagem. Para uma função em linguagem SQL, são as instruções SQL que compõem o corpo da função.

**`RETURN {{expression}}`**  
Define o corpo da função usando a sintaxe padrão SQL para uma função que exibe uma única expressão. Essa é uma alternativa à forma constante de string.

**`BEGIN ATOMIC {{statement}}; [ ... ] END`**  
Define o corpo da função usando a sintaxe padrão SQL. O corpo consiste em uma ou mais instruções SQL. Este formulário só é válido para `LANGUAGE sql`. As declarações em um corpo atômico são rastreadas como dependências da função. Por exemplo, uma tabela referida no corpo não pode ser descartada sem também eliminar a função ou que se use `DROP ... CASCADE`.

## Observações
<a name="create-function-notes"></a>

Use a instrução `DROP FUNCTION` para remover uma função. Você também pode conceder e revogar privilégios em uma função com `GRANT` e `REVOKE` (por exemplo, `REVOKE ALL ON FUNCTION`).

Qualquer função que lê ou modifica dados em tabelas está sujeita ao mesmo comportamento de transação e simultaneidade que as instruções SQL equivalentes executadas diretamente. Funções declaradas `IMMUTABLE` ou `STABLE` não devem modificar o banco de dados.

Para atualizar a definição atual de uma função existente, use `CREATE OR REPLACE FUNCTION`. Você não pode alterar os tipos de argumentos nem o tipo de retorno de uma função dessa forma; em vez disso, descarte e recrie a função.

Para renomear uma função, alterar seu proprietário ou mova-a para outro esquema, use `ALTER FUNCTION`. Para alterar qualquer outro atributo, use `CREATE OR REPLACE FUNCTION` com as alterações desejadas. Para obter mais informações, consulte [`ALTER FUNCTION`](alter-function-syntax-support.md).

A sobrecarga de funções é aceita: você pode definir várias funções com o mesmo nome, desde que seus tipos de argumentos de entrada sejam diferentes. Uma função definida pelo usuário também pode chamar outras funções e pode sombrear uma função interna com o mesmo nome e tipos de argumento.

Para uma função que exibe um conjunto (`SETOF` ou `RETURNS TABLE`) cujo corpo contém mais de uma instrução, somente o resultado da declaração final é exibido. A função ainda executa as instruções anteriores, mas descarta seus resultados. Esse é o comportamento padrão das funções da linguagem SQL. Estruture a função para que sua declaração final produza o conjunto completo de resultados.

Uma função que exibe um conjunto não garante nenhuma ordem de linhas específica. Para controlar a ordem das linhas, inclua uma cláusula `ORDER BY` na consulta.

## Considerações
<a name="create-function-considerations"></a>

Os recursos `CREATE FUNCTION` a seguir exibem o erro mostrado.

**`LEAKPROOF`**  
Exibe o erro `only superuser can define a leakproof function`. `NOT LEAKPROOF` (o padrão) é aceito.

**`TRANSFORM FOR TYPE`**  
Exibe o erro `transform for type {{type}} language "sql" does not exist`.

**`SUPPORT` (função de suporte do planejador)**  
Exibe o erro `function {{name}}(internal) does not exist`.

**Tipos compostos definidos pelo usuário (`CREATE TYPE ... AS`), incluindo funções que exibem um tipo composto**  
Exibe o erro `unsupported statement: CompositeType`.

O Aurora DSQL não comporta `CREATE PROCEDURE`, o que resulta no erro `PROCEDURE is not supported`.

O atributo `WINDOW` é aceito sintaticamente, mas não é útil para funções da linguagem SQL. Evite usar esse atributo.

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

Crie uma função SQL simples que adicione dois números inteiros, usando um corpo constante de string:

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

Crie a mesma função usando o corpo `RETURN` padrão SQL e os argumentos nomeados:

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

Crie uma função que exiba um conjunto de linhas usando `RETURNS TABLE` e um corpo `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;
```

Crie uma função que seja executada com os privilégios de seu proprietário e defina um parâmetro de configuração para a duração da chamada:

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

## Compatibilidade
<a name="create-function-compatibility"></a>

Um comando `CREATE FUNCTION` é definido no padrão SQL. A implementação do PostgreSQL pode ser usada de forma compatível, mas tem muitas extensões. Por outro lado, o padrão SQL especifica vários recursos opcionais que não são implementados no PostgreSQL.

Veja a seguir problemas importantes de compatibilidade:
+ `OR REPLACE` é uma extensão da linguagem PostgreSQL.
+ Para compatibilidade com alguns outros sistemas de banco de dados, {{argmode}} pode ser escrito antes ou depois de {{argname}}. Mas somente a primeira forma é compatível com os padrões.
+ Para padrões de parâmetros, o padrão SQL especifica somente a sintaxe com a palavra-chave `DEFAULT`. A sintaxe com `=` é usada no T-SQL e no Firebird.
+ O modificador `SETOF` é uma extensão do PostgreSQL.
+ Somente o SQL é padronizado como linguagem.
+ Todos os outros atributos, exceto `CALLED ON NULL INPUT` e `RETURNS NULL ON NULL INPUT`, não são padronizados.
+ Para o corpo das funções `LANGUAGE sql`, o padrão SQL especifica apenas o formato {{sql\_body}}.

Funções `LANGUAGE sql` simples podem ser escritas de uma forma que esteja em conformidade com os padrões e portátil para outras implementações. Funções mais complexas usando recursos avançados, atributos de otimização ou outras linguagens serão necessariamente específicas do PostgreSQL de forma significativa.