Provavelmente, o principal motivo é que as funções com valor de tabela retornam um conjunto de resultados, assim como tabelas e visualizações. Isto significa que eles podem ser utilizados na FROM
cláusula (incluindo JOIN
s e APPLY
s, etc.) de SELECT
, UPDATE
e DELETE
consultas. No entanto, você não pode usar um UDF escalar em nenhum desses contextos.
Secundariamente, você também pode EXECUTE
um UDF escalar. Essa sintaxe é bastante útil quando você tem valores padrão especificados para parâmetros de entrada. Pegue a seguinte UDF, por exemplo:
CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
RETURN @Param1 + @Param2;
END;
Se você quiser tratar qualquer um dos parâmetros de entrada como "opcional", ainda precisará passar a DEFAULT
palavra - chave ao chamá-la como uma função, pois a assinatura foi corrigida:
DECLARE @Bob1 INT;
SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);
SELECT @Bob1;
-- Returns: 102
Por outro lado, se você EXECUTE
usar a função, poderá tratar qualquer parâmetro com um valor padrão como verdadeiramente opcional, assim como em Procedimentos Armazenados. Você pode passar os primeiros n parâmetros sem especificar os nomes dos parâmetros:
DECLARE @Bob2 INT;
EXEC @Bob2 = dbo.OptionalParameterTest 50;
SELECT @Bob2;
-- Returns: 52
Você pode até pular o primeiro parâmetro especificando nomes de parâmetros novamente, como nos Procedimentos armazenados:
DECLARE @Bob3 INT;
EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;
SELECT @Bob3;
-- Returns: 51
ATUALIZAR
Por que você deseja usar a EXEC
sintaxe para chamar um UDF escalar como um Procedimento Armazenado? Ocasionalmente, existem UDFs que são ótimos para ter como UDFs, pois podem ser adicionados a uma consulta e operar sobre o conjunto de linhas retornadas, enquanto que, se o código estivesse em um Procedimento armazenado, seria necessário colocá-lo em um cursor para itere sobre um conjunto de linhas. Mas há momentos em que você deseja chamar essa função em um único valor, possivelmente de outro UDF. A chamada de um UDF para um único valor pode ser feita como:
SELECT dbo.UDF('some value');
nesse caso, você obtém um valor de retorno em um conjunto de resultados (um conjunto de resultados não funciona). Ou isso pode ser feito da seguinte maneira:
DECLARE @Dummy INT;
SET @Dummy = dbo.UDF('some value');
nesse caso, você precisa declarar a @Dummy
variável;
NO ENTANTO, com a EXEC
sintaxe, você pode evitar os dois aborrecimentos:
EXEC dbo.UDF 'some value';
Além disso, as UDFs escalares têm seus planos de execução em cache. Isso significa que é possível encontrar problemas de detecção de parâmetros se houver consultas no UDF que possuam planos de execução. Para cenários em que é possível usar a EXEC
sintaxe, também é possível usar a WITH RECOMPILE
opção de ignorar o valor compilado dos planos para essa execução . Por exemplo:
CONFIGURAÇÃO:
GO
CREATE FUNCTION dbo.TestUDF (@Something INT)
RETURNS INT
AS
BEGIN
DECLARE @Ret INT;
SELECT @Ret = COUNT(*)
FROM sys.indexes si
WHERE si.[index_id] = @Something;
RETURN @Ret;
END;
GO
TESTE:
DECLARE @Val INT;
SET @Val = dbo.TestUDF(1);
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 -- uses compiled value of (1)
SELECT @Val;
EXEC @Val = dbo.TestUDF 0 WITH RECOMPILE; -- uses compiled value of (0)
SELECT @Val;
EXEC @Val = dbo.TestUDF 3 -- uses compiled value of (1)
SELECT @Val;