Tengo una pregunta sobre una pieza de documentación sobre tablas temporales que leí recientemente en TechNet . El cuarto párrafo de la sección de Tablas temporales en esa página dice lo siguiente:
Si se crea una tabla temporal con una restricción con nombre y la tabla temporal se crea dentro del alcance de una transacción definida por el usuario, solo un usuario a la vez puede ejecutar la instrucción que crea la tabla temporal. Por ejemplo, si un procedimiento almacenado crea una tabla temporal con una restricción de clave primaria nombrada, el procedimiento almacenado no puede ser ejecutado simultáneamente por múltiples usuarios.
Trabajo en un entorno donde hacemos un uso significativo de un puñado de procedimientos almacenados que usan tablas temporales indexadas, y nunca hemos encontrado un problema en el que los usuarios tengan que esperar a que se complete una ejecución antes de que comience la siguiente. Espero que siga siendo así, pero me preocupa que pueda convertirse en un problema si esta advertencia no se entiende correctamente.
Específicamente, no estoy claro sobre los siguientes puntos:
- ¿Esto se aplica solo a las tablas temporales globales, o también a las locales? Parece extraño que una tabla que no sea visible fuera de la sesión (como en el último caso) impida que otra sesión se ejecute simultáneamente.
- ¿Qué califica como una "restricción con nombre"? ¿No todas las restricciones tienen nombres (incluso si son generados por el sistema)? ¿Se refiere esto a restricciones con un alias definido por el usuario? Esto me parece una frase pobre.
- ¿"Usuarios múltiples" en realidad significa sesiones múltiples? Estos procedimientos se llaman a través de nuestra aplicación utilizando una sola cuenta de servicio, por lo que el 99.9% de las llamadas a nuestros scripts se realizan a la base de datos por esa cuenta única (y no me preocupa la llamada ocasional que un administrador puede hacer en el back-end). Si la cuenta de servicio puede ejecutar el sproc en varias sesiones simultáneamente, entonces este problema es discutible para mis propósitos.
fuente
Respuestas:
Creo que no puedes tener nombres duplicados
tempdb.sys.key_constraints
. Esto es lo que hay en esa vista de metadatos en uno de mis servidores:Todos los nombres impares que terminan con
_6E...
fueron generados automáticamente por SQL Server. No tienen restricciones de nombre porque no les di explícitamente un nombre al crearlas. SQL Server genera un nombre de restricción detrás de escena que, en teoría, evita las colisiones de nombres.Si intento crear la siguiente tabla en dos sesiones diferentes:
El que se ejecuta en segundo lugar arroja un error:
Mirando la vista nuevamente:
Si intento crear la siguiente tabla en dos sesiones, no hay problema:
Aquí está la vista de metadatos:
Solo para responder a sus preguntas directamente: la parte que citó se aplica tanto a las tablas temporales locales como a las globales, una restricción con nombre es aquella en la que le da un nombre deliberadamente, y varios usuarios significan varias sesiones.
fuente
Esto se aplica a las tablas temporales locales.
La diferencia entre las restricciones con nombre y sin nombre es esta:
Dejar las restricciones de nombre del sistema hace que sea extremadamente improbable que haya una colisión. En este ejemplo, si abre dos ventanas en SSMS, podrá crear
#t1
en ambas, pero no#t2
.Las tablas temporales globales son compartidas por todos los usuarios, por lo que debe manejar las cosas de manera diferente. No se 'destruyen' hasta que la última sesión haya terminado de usarlos, por lo que debe asegurarse de que cuando los usuarios accedan a ellos, solo puedan acceder a sus datos. Esto a veces se realiza mediante SPID, otras veces mediante un valor hash. Depende de cómo se use la tabla temporal global.
Por lo general, para las tablas temporales globales, los procedimientos almacenados verifican si existen y luego solo los crean si
OBJECT_ID()
es asíNULL
.Múltiples usuarios significa múltiples sesiones. El nombre de usuario no tiene nada que ver con eso. Si George corre
sp_something @i = 1
y Gina corresp_something @i = 2
, no importa si ambos están conectadosUser1
, tendrán diferentes SPID.fuente