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 FROM
cláusula (incluyendo JOIN
s y APPLY
s, etc.) de SELECT
, UPDATE
y DELETE
consultas. Sin embargo, no puede utilizar un UDF escalar en ninguno de esos contextos.
En segundo lugar, también puede EXECUTE
un 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 DEFAULT
palabra 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 EXECUTE
la 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 EXEC
sintaxis 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 @Dummy
variable;
SIN EMBARGO, con la EXEC
sintaxis, 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 EXEC
sintaxis, también es posible usar la WITH RECOMPILE
opció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;