Ao criar uma função com valor de tabela (TVF) no SQL Server, você pode torná-la uma função com valor de tabela embutida (ITVF) ou uma função com valor de tabela de várias instruções (MSTVF). Existem diferenças entre esses tipos de função e eles usam uma sintaxe diferente de acordo.
Este artigo aborda a diferença entre MSTVFs e ITVFs.
As diferenças
Aqui estão as principais diferenças entre MSTVFs e ITVFs.
| ITVF | MSTVF | |
|---|---|---|
| A sintaxe de RETURNS | Você simplesmente declara RETURNS TABLE e a definição da tabela de retorno será baseada no SELECT da função demonstração. Não há necessidade de especificar a estrutura da tabela de retorno. | Seus RETURNS sintaxe especifica explicitamente a estrutura da tabela de retorno. Isso é feito declarando uma variável TABLE que será usada para armazenar e acumular as linhas que são retornadas como o valor da função. |
| A sintaxe BEGIN/END | ITVFs não usam o BEGIN /END sintaxe. | MSTVFs usam o BEGIN /END sintaxe. |
| Desempenho | Geralmente mais rápido que os MTSVFs. | Geralmente mais lento que ITVFs. |
| Atualizações de dados | Em alguns casos, é possível atualizar dados nas tabelas subjacentes usando um ITFV. | Você não pode atualizar dados nas tabelas subjacentes usando um MSTVF. |
Sintaxe
Vejamos as diferenças na sintaxe de cada tipo de função.
Função com valor de tabela embutido
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [ READONLY ] }
[ ,...n ]
]
)
RETURNS TABLE
[ WITH <function_option> [ ,...n ] ]
[ AS ]
RETURN [ ( ] select_stmt [ ) ]
[ ; ]
Função com valor de tabela de várias instruções
CREATE [ OR ALTER ] FUNCTION [ schema_name. ] function_name
( [ { @parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [READONLY] }
[ ,...n ]
]
)
RETURNS @return_variable TABLE <table_type_definition>
[ WITH <function_option> [ ,...n ] ]
[ AS ]
BEGIN
function_body
RETURN
END
[ ; ]
Observe que o MSTVF inicia com uma definição de tabela, mas o ITVF não possui tal definição.
O MSTVF começa com
RETURNS @return_variable TABLE seguido pela definição da tabela. Aqui, @return_variable é uma variável TABLE, usada para armazenar e acumular as linhas que devem ser retornadas como o valor da função. Exemplo 1 – Função com valor de tabela embutido
Aqui está um exemplo de um ITVF simples.
CREATE FUNCTION udf_PetsByName_ITVF( @PetName varchar(70))
RETURNS TABLE
AS
RETURN (
SELECT
CONCAT('Cat', ' ', CatId) AS PetId,
CatName
FROM dbo.Cats
WHERE CatName = @PetName
UNION ALL
SELECT
CONCAT('Dog', ' ', DogId) AS PetId,
DogName
FROM dbo.Dogs
WHERE DogName = @PetName
);
GO
Aqui, eu seleciono entre duas tabelas usando
UNION ALL , e a função simplesmente retorna o resultado. Exemplo 2 - Função com valor de tabela de várias instruções
Aqui está um exemplo de uso de um MSTVF para fazer a mesma coisa, mas de uma maneira diferente.
CREATE FUNCTION udf_PetsByName_MSTVF( @PetName varchar(70))
RETURNS @pets TABLE (
PetId varchar(20),
PetName varchar(70)
)
AS
BEGIN
INSERT INTO @pets
SELECT
CONCAT('Cat', ' ', CatId),
CatName
FROM dbo.Cats
WHERE CatName = @PetName;
INSERT INTO @pets
SELECT
CONCAT('Dog', ' ', DogId),
DogName
FROM dbo.Dogs
WHERE DogName = @PetName;
RETURN;
END;
GO
A função começa declarando uma variável TABLE chamada
@pets . Ao fazer isso, especificamos explicitamente a estrutura da tabela de retorno. As consultas dentro do
BEGIN /END bloco são salvos na variável TABLE chamada @pets . Nesse caso, optei por não usar
UNION ALL . Em vez disso, executei as instruções separadamente e salvei os resultados de cada uma no @pets variável. Exemplo 3 – Adicionar outra declaração ao MSTVF
Para demonstrar ainda mais o aspecto “multi-instrução” dos MSTVFs, podemos adicionar mais instruções ao MSTVF acima e salvar os resultados na mesma variável de retorno.
Exemplo:
CREATE FUNCTION udf_PetsByName_MSTVF( @PetName varchar(70))
RETURNS @pets TABLE (
PetId varchar(20),
PetName varchar(70)
)
AS
BEGIN
INSERT INTO @pets
SELECT
CONCAT('Cat', ' ', CatId),
CatName
FROM dbo.Cats
WHERE CatName = @PetName;
INSERT INTO @pets
SELECT
CONCAT('Dog', ' ', DogId),
DogName
FROM dbo.Dogs
WHERE DogName = @PetName;
IF @@ROWCOUNT = 0
BEGIN
INSERT INTO @pets
VALUES (
'',
'There are no pets of that name.'
)
END
RETURN;
END;
GO
Nesse caso, adicionei algum código para retornar uma mensagem especial sempre que a consulta não resultar em nenhuma linha retornada.