switch example español ejemplos sql-server tsql sql-server-2014 apply outer-apply

sql-server - example - select coalesce sql server



El valor se devuelve en lugar de NULL cuando se usa la función con APLICACIÓN EXTERNA (3)

Esta es una consulta muy interesante. El comportamiento de su primera consulta depende de si utiliza OPTION (RECOMPILE) o no.

Como usted señala, esto:

DECLARE @u CHAR(12) = ''066BDLER'' SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY [dbo].[vendor_relation_users](@u) AS is_v

devuelve esto:

user_name user_name 066BDLER 066BDLER

pero si agrega OPTION (RECOMPILE) esta manera:

SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY [dbo].[vendor_relation_users](@u) AS is_v OPTION (RECOMPILE)

correctamente obtienes esto:

user_name user_name 066BDLER NULL

Sospecho que esto se debe a un error en la forma en que el optimizador de consultas cortocircuita estas funciones en línea debido a las estimaciones de cardinalidad. Si observa el plan de consultas para las dos consultas, verá que el que no tiene OPTION RECOMPILE solo devuelve una constante.

Estoy obteniendo resultados extraños cuando uso la función en línea. Aquí está el código:

IF EXISTS ( SELECT * FROM sys.objects AS o WHERE name = ''vendor_relation_users'' ) DROP FUNCTION dbo.vendor_relation_users; GO CREATE FUNCTION [dbo].[vendor_relation_users] ( @user_name CHAR(12) ) RETURNS TABLE AS RETURN (SELECT @user_name AS user_name WHERE @user_name NOT LIKE ''06%''); GO DECLARE @u CHAR(12) = ''066BDLER'' SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY [dbo].[vendor_relation_users](@u) AS is_v SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY (SELECT @u AS user_name WHERE @u NOT LIKE ''06%'') AS is_v SELECT * FROM [dbo].[vendor_relation_users](@u)

Así que en la primera instrucción SELECT acabo de APLICAR LA FUNCIÓN y devuelve el resultado.

En la siguiente declaración, tomé el código de la función y lo puse directamente en la instrucción OUTER APPLY.

Y la última afirmación es solo la llamada a la función directa.

No puedo entender por qué la PRIMERA consulta devuelve el valor ...


Supongo que es un viejo bicho descrito here . Y está Closed as Won''t Fix

Por favor use esta función como:

SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY ( SELECT * FROM [dbo].[vendor_relation_users](a.user_name) ) AS is_v

ACTUALIZACIÓN # 1

Solo lee los comentarios:

Podría ser el mismo problema básico que aquí .com/a/32414450/73226 - Martin Smith

¡Eso es! Mismo problema, mismo enlace que he proporcionado al sitio de MS Connect.

ACTUALIZACIÓN # 2

En lugar:

RETURN (SELECT @user_name AS user_name WHERE @user_name NOT LIKE ''06%'');

Necesitas usar:

RETURN (SELECT CASE WHEN @user_name LIKE ''06%'' THEN NULL ELSE @user_name END)


CREATE FUNCTION [dbo].[vendor_relation_users] ( @user_name CHAR(12) ) RETURNS TABLE AS RETURN (SELECT CASE WHEN @user_name NOT LIKE ''06%'' THEN @user_name ELSE NULL END as [user_name]); GO

Bien, https://docs.microsoft.com/en-us/sql/t-sql/language-elements/select-local-variable-transact-sql

Si la instrucción SELECT no devuelve ninguna fila, la variable conserva su valor presente. Si expresión es una subconsulta escalar que no devuelve ningún valor, la variable se establece en NULL.

Por ejemplo

DECLARE @u CHAR(12) = ''066BDLER'' SELECT @u = ''AAAA'' WHERE 1 <> 1 SELECT @u

Bajo cualquier condición, el valor de SELECT @variable no cambiará, y DB ENGINE simplifica la declaración para

| - Exploración constante

Si usa RECOMPILE sql, cree un nuevo plan con condiciones y cambios en el plan

|--Compute Scalar(DEFINE:([Expr1001]=''066BDLER '')) |--Filter(WHERE:(STARTUP EXPR(NOT ''066BDLER '' like ''06%''))) |--Constant Scan

Pero RECOMPILE requiere costos de compilación, luego use CASE para la devolución

ps. Si no cambia la función, puede omitir la asignación, de lo contrario, ¿por qué se APLICARÁ :)

DECLARE @u CHAR(12) = ''066BDLER'' SELECT a.user_name, is_v.user_name FROM (SELECT @u AS user_name) a OUTER APPLY [dbo].[vendor_relation_users](a.user_name) AS is_v