No SQL Server, você pode criar uma função escalar definida pelo usuário usando a função
CREATE FUNCTION
demonstração. Uma função escalar definida pelo usuário, também conhecida como UDF escalar, é uma função definida pelo usuário que retorna um único valor. Este artigo contém exemplos de criação de algumas UDFs escalares T-SQL básicas.
Sintaxe
Primeiro, vamos ver a sintaxe para criar UDFs escalares.
A sintaxe para UDFs escalares T-SQL é assim:
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( [ { @parameter_name [ AS ][ type_schema_name. ] parameter_data_type [ =default ] [ READONLY ] } [ ,...n ] ] ) RETURNS return_data_type [ WITH[ ,...n ] ] [ AS ] BEGIN corpo_função RETURN expressão_escalar END [; ]
E a sintaxe para UDFs escalares CLR:
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name ( { @parameter_name [AS] [ type_schema_name. ] parameter_data_type [ =default ] } [ ,...n ] ) RETURNS { return_data_type } [ WITH[ ,...n ] ] [ AS ] EXTERNAL NAME [; ]
As partes em
<function_option>
para funções T-SQL e <clr_function_option>
para funções CLR permitem especificar opções para a UDF. As opções de função incluem adicionar criptografia, vinculação de esquema, um EXECUTE AS
cláusula, bem como especificar o que fazer quando um valor NULL é passado como argumento. Uma lista completa de argumentos e opções de função pode ser encontrada no site da Microsoft.
A documentação da Microsoft contém muitos detalhes, portanto, os exemplos a seguir visam fornecer uma visão geral rápida de alguns conceitos e opções comuns ao criar UDFs escalares.
Exemplo 1 – UDF escalar básica
Aqui está um exemplo do código usado para criar uma UDF escalar T-SQL básica.
CREATE FUNCTION dbo.ufn_discountPrice( @price DECIMAL(12,2), @discount DECIMAL(12,2) ) RETURNS DECIMAL (12,2)ASBEGIN RETURN @price * (1 - @discount);END;
Essa UDF escalar aceita dois parâmetros;@price
e@discount
. Estes são passados para a função como argumentos sempre que a função é invocada. A função recebe o valor desses argumentos, executa um cálculo usando esses valores e retorna o valor resultante. Neste caso, o preço com desconto é devolvido.
Exemplo 2 – Invocar a UDF
Depois que a UDF for criada, ela poderá ser invocada no código T-SQL sempre que você precisar.
Aqui está um exemplo de invocar a UDF:
SELECT dbo.ufn_discountPrice(100, .2) AS Resultado;
Resultado
+----------+| Resultado ||----------|| 80,00 |+----------+Exemplo 3 – Consultando uma tabela
UDFs escalares também podem fazer coisas como consultar tabelas de banco de dados.
Aqui está um que retorna o número de álbuns no banco de dados de um determinado artista.
CRIAR FUNÇÃO dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallintAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;
Esta é uma função escalar porque ela retorna um único valor. Se quiséssemos retornar uma lista de álbuns, precisaríamos usar uma função com valor de tabela, porque funções com valor de tabela retornam seus resultados como um conjunto de linhas.
Exemplo 4 – Vinculação de esquema
Quando você cria uma função definida pelo usuário que depende de outros objetos no banco de dados, geralmente é uma boa ideia vincular o UDF ao esquema. O esquema de vinculação da UDF garante que nenhuma alteração possa ser feita nos objetos subjacentes que possam afetar a função.
Por exemplo, você não poderá descartar uma tabela que uma UDF vinculada ao esquema usa em sua definição.
Para associar um esquema a uma UDF, useWITH SCHEMABINDING
em sua definição. Você também precisa usar nomes de duas partes para todos os objetos referenciados na UDF.
Aqui está o exemplo anterior reescrito para que seja vinculado ao esquema:
CRIAR FUNÇÃO dbo.ufn_CountAlbums (@ArtistId int) RETORNOS smallintCOM SCHEMABINDINGAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;
Então, eu mudei duas coisas do primeiro exemplo. Eu adicioneiWITH SCHEMABINDING
, e altereiAlbums
paradbo.Albums
.
Agora, se alguém tentar descartar essa tabela ou fazer outras alterações nela, receberá um erro.
Exemplo 5 – Criptografia
Você também pode usarWITH ENCRYPTION
para criptografar a função.
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETORNOS smallintWITH ENCRYPTIONAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;Exemplo 6 – Entrada NULA
Ao invocar a função, se algum dos argumentos for NULL, o corpo da função ainda será executado. Ou seja, a menos que você tenha declarado explicitamenteRETURNS NULL ON NULL INPUT
na definição da função.
Especificar essa opção retornará NULL se algum dos argumentos for NULL.
CREATE FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETURNS smallintWITH RETURNS NULL ON NULL INPUTAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;
Quando invoco a função usando NULL como argumento:
SELECT dbo.ufn_CountAlbums(NULL) AS Resultado;
Obtenho um resultado diferente, dependendo do que especifiquei para esta opção.
Aqui está o resultado quando a função usa a configuração padrão (CALLED ON NULL INPUT
):
+----------+| Resultado ||----------|| 0 |+----------+
E aqui está o resultado quando ele usaRETURNS NULL ON NULL INPUT
:
+----------+| Resultado ||----------|| NULL |+----------+Exemplo 7 – Várias opções
Você pode separar várias opções com uma vírgula.
Aqui está um exemplo que adiciona criptografia e vinculação de esquema à função:
CRIAR FUNÇÃO dbo.ufn_CountAlbums (@ArtistId int) RETORNOS smallintCOM CRIPTOGRAFIA, SCHEMABINDINGAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;Exemplo 8 – Alterar uma função
Você pode alterar uma UDF escalar substituindoCREATE
comALTER
.
ALTER FUNCTION dbo.ufn_CountAlbums (@ArtistId int) RETORNOS smallintWITH SCHEMABINDINGAS BEGIN DECLARE @AlbumCount int; SELECT @AlbumCount =COUNT(AlbumId) FROM dbo.Albums WHERE ArtistId =@ArtistId; RETURN @AlbumCount;END;