¿Es aconsejable usar una tabla temporal cuando el procedimiento almacenado podría ser ejecutado simultáneamente por diferentes usuarios?

8

Estoy trabajando en un procedimiento almacenado que recupera el objectGUID del directorio activo. Estoy almacenando el resultado en una tabla temporal y luego devolviendo el valor en un parámetro de salida para usar con otros procesos. Se llamará al SP desde diferentes procedimientos almacenados, así como desde aplicaciones web PHP, ASP Classic y ASP.Net.

Leí AQUÍ que (con respecto a las tablas temporales):

Si se crean dentro de un procedimiento almacenado, se destruyen al finalizar el procedimiento almacenado. Además, el alcance de cualquier tabla temporal particular es la sesión en la que se crea; lo que significa que solo es visible para el usuario actual. Varios usuarios podrían crear una tabla temporal llamada #TableX y las consultas que se ejecuten simultáneamente no se afectarían entre sí: seguirían siendo transacciones autónomas y las tablas seguirían siendo objetos autónomos. Puede notar que mi nombre de tabla temporal de muestra comenzó con un signo "#".

Parece que estoy listo para ir, pero quería obtener algunos consejos para asegurarme de que no hay problemas que desconozco. Aquí está el SP.

Gracias por adelantado.

CREATE PROCEDURE stp_adlookup
@user varchar(100),
@objectGUID varbinary(256) OUTPUT
AS
SET NOCOUNT ON;
DECLARE @qry char(1000)
CREATE TABLE #tmp(
objectGUID nvarchar(256)
)

SET @qry = 'SELECT *
FROM openquery(ADSI, ''
SELECT  objectGUID              
FROM    ''''LDAP://mydomaincontroller.com''''
WHERE sAMAccountName = ''''' + @user + '''''
'')'
INSERT INTO #tmp
EXEC(@qry)
SELECT @objectGUID=CAST(objectGUID as varbinary(256))  FROM #tmp;
DROP TABLE #tmp
SET NOCOUNT OFF;
GO
usuario1633947
fuente

Respuestas:

15

Sí, cada usuario obtendrá su propia copia de la tabla #temp, incluso si se ejecutan exactamente al mismo tiempo.

(Sin embargo, no use tablas temporales globales ##, indicadas con dos signos principales de libra / hash).

Pero, ¿por qué necesitas una tabla #temp aquí? Algo como esto debería funcionar (no probado, ya que no tengo LDAP cerca de mí):

CREATE PROCEDURE dbo.stp_adlookup -- ALWAYS use schema prefix
  @user varchar(100),
  @objectGUID varbinary(256) OUTPUT
AS
BEGIN -- use body wrappers
  SET NOCOUNT ON;

  DECLARE @qry nvarchar(max); -- don't use CHAR for dynamic SQL

  SET @qry = N'SELECT @o = objectGUID
    FROM openquery(ADSI, ''SELECT  objectGUID              
      FROM    ''''LDAP://mydomaincontroller.com''''
      WHERE sAMAccountName = ''''' + @user + ''''''')';

  -- can probably parameterize the above, but those single
  -- quotes are a nightmare. Not sure if they're necessary
  -- but I do not feel like trying to untangle them.

  EXEC sys.sp_executesql @qry, N'@o UNIQUEIDENTIFIER', @o = @objectGUID OUTPUT;

  -- SET NOCOUNT OFF; -- don't do this.
END
GO
Aaron Bertrand
fuente
8

Debería estar bien, tenemos innumerables SP aquí que se ejecutan miles de veces al día con tablas temporales que se llaman igual y no tienen ningún problema.

Aquí hay un ejemplo visual. He creado 2 tablas en mi instancia SQL2014. Uno fue creado a partir de SPID 53, el otro a partir de SPID 57. Así es como se ve en Object Explorer:

ingrese la descripción de la imagen aquí

Como puede ver, aunque se 'nombran' de la misma manera, al final, hay un conjunto encantador de personajes que hacen que las tablas sean diferentes. La única diferencia es que ejecuté las declaraciones CREATE desde diferentes ventanas de consulta. Esta es solo una forma visual de mostrarlo. Cuando consulta la tabla #tmp, solo consulta la tabla que se aplica a su sesión.

Sin embargo, haré una sugerencia. Es algo de lo que soy completamente culpable y estoy trabajando en la transición. Usar en sp_executesqllugar de EXEC(). Aaron Bertrand escribió esto como uno de los 'malos hábitos para patear':

Básicamente, el uso de sp_executesql reducirá la posibilidad de inyección de SQL y existe una mayor probabilidad de que el plan de ejecución pueda reutilizarse. Aaron entra en mucho más detalle en el artículo, pero esa es la vista de 1000 pies.

Kris Gruttemeyer
fuente
55
Solo agregaría que puede ser útil nombrar tablas temporales locales de manera única por procedimiento, porque el procedimiento puede llamarse desde otro procedimiento que ya ha creado una tabla temporal local con el mismo nombre.
Paul White 9
2

en un sentido amplio, estarás bien haciéndolo de esta manera. Los procedimientos almacenados tienen un alcance limitado, por lo que, aunque (ejemplo) 3 usuarios ejecutan el mismo procedimiento almacenado y las tablas temporales no se mezclan, ni siquiera se verán.

Siempre y cuando no necesite compartir los resultados con una sesión diferente o un usuario que ejecute un proceso diferente, la tabla Temp podría ser una buena opción.

Brad D
fuente