Lo más probable es que la razón principal sea que las funciones con valores de tabla devuelven un conjunto de resultados, al igual que las tablas y vistas. Esto significa que se pueden utilizar en la FROMcláusula (incluyendo JOINs y APPLYs, etc.) de SELECT, UPDATEy DELETEconsultas. Sin embargo, no puede utilizar un UDF escalar en ninguno de esos contextos.
En segundo lugar, también puede EXECUTEun UDF escalar. Esta sintaxis es bastante útil cuando tiene valores predeterminados especificados para los parámetros de entrada. Tome el siguiente UDF, por ejemplo:
CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
    RETURN @Param1 + @Param2;
END;
Si desea tratar cualquiera de los parámetros de entrada como "opcional", aún necesita pasar la DEFAULTpalabra clave al llamarla como una función ya que la firma es fija:
DECLARE @Bob1 INT;
SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);
SELECT @Bob1;
-- Returns: 102
Por otro lado, si utiliza EXECUTEla función, puede tratar cualquier parámetro con un valor predeterminado como realmente opcional, tal como puede hacerlo con los procedimientos almacenados. Puede pasar los primeros n parámetros sin especificar los nombres de los parámetros:
DECLARE @Bob2 INT;
EXEC @Bob2 = dbo.OptionalParameterTest 50;
SELECT @Bob2;
-- Returns: 52
Incluso puede omitir el primer parámetro especificando nombres de parámetros, nuevamente, al igual que con los Procedimientos almacenados:
DECLARE @Bob3 INT;
EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;
SELECT @Bob3;
-- Returns: 51
ACTUALIZAR
¿Por qué querrías usar la EXECsintaxis para llamar a un UDF escalar como un procedimiento almacenado? Ocasionalmente, hay UDF que es genial tener como UDF ya que se pueden agregar a una consulta y operar sobre el conjunto de filas devueltas, mientras que si el código estuviera en un Procedimiento almacenado, entonces debería colocarse en un cursor para iterar sobre un conjunto de filas. Pero luego hay veces que desea llamar a esa función con un solo valor, posiblemente desde otro UDF. Llamar a un UDF por un solo valor se puede hacer como:
SELECT dbo.UDF('some value');
en cuyo caso obtendrá un valor de retorno en un conjunto de resultados (un conjunto de resultados no funcionará). O podría hacerse de la siguiente manera:
DECLARE @Dummy INT;
SET @Dummy = dbo.UDF('some value');
en cuyo caso necesita declarar la @Dummyvariable;
SIN EMBARGO, con la EXECsintaxis, puede evitar ambas molestias:
EXEC dbo.UDF 'some value';
TAMBIÉN, los UDF escalares tienen sus planes de ejecución en caché. Esto significa que es posible encontrarse con problemas de detección de parámetros si hay consultas en el UDF que tienen planes de ejecución. Para escenarios donde es factible usar la EXECsintaxis, también es posible usar la WITH RECOMPILEopción de ignorar el valor compilado de los planes para esa ejecución . Por ejemplo:
PREPARAR:
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
PRUEBA:
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;