2009-10-15 24 views
5

Estoy trabajando en la próxima actualización de StackQL.¿Puedo establecer un esquema predeterminado dentro de un procedimiento almacenado?

Una cosa que quiero hacer es tener la capacidad de consultar en varios lanzamientos. Entonces, cuando cargué los datos de octubre, por ejemplo, no eliminé la antigua base de datos de septiembre. Aún está por ahí. De hecho, incluso se puede consultar aún que al incluir el nombre de la base de esta manera:

select top 10 * from SO_Sept09..Posts 

Esto va a ser aún más importante a medida que empiezan proporcionar datos para ServerFault y superusuario.

Pero no me gusta tener un montón de bases de datos para apoyar esto. Preferiría poner todos los datos en la misma base de datos y separar cada conjunto distinto en su propio esquema. Pero para que esto sea posible, necesito poder establecer un esquema predeterminado como parte del procedimiento almacenado que ejecuta la consulta, en función de un parámetro pasado al procedimiento almacenado que le dice qué base de datos seleccionó el usuario de una lista desplegable futura. para aparecer en la barra de herramientas.

consultas en StackQL son finalmente acaba de pasar a la función exec() así:

exec(@QueryText) 

¿Hay algo que pueda hacer, ya sea en el procedimiento almacenado o anteponer a la cadena QueryText (ala USE [DatabaseName]) para establecer el valor predeterminado esquema utilizado en una consulta?

+0

¡Excelente pregunta! – RBarryYoung

Respuesta

3

Aparte de la modificación @QueryText sí mismo, lo único que puedo pensar es esquema predeterminado de un usuario:

ALTER USER SO_Sept09_Reader WITH DEFAULT_SCHEMA = SO_Sept09 

... y luego conectar como un usuario diferente para cada esquema que desea utilizar. Hackity hack.

Pero si su consulta se construye dinámicamente de todos modos (y estoy seguro de que sabe por qué a menudo no es una gran idea), sería más fácil agregar un marcador de posición de esquema al texto de consulta y pasar el nombre de esquema junto con la consulta a una función de reemplazo.

+0

Agregar un marcador de posición de esquema definitivamente no es una opción. El sitio permite a cualquier persona escribir y ejecutar una consulta sql de nuevo el volcado de datos públicos de StackOverflow, y puede escribir casi cualquier cosa. El usuario alterado también está fuera, ya que eso causaría problemas de concurrencia. Pero me da la idea de tal vez tener varios usuarios y elegir la cadena de conexión sobre la marcha. –

+0

Sí, este último es lo que sugerí; uno o más usuarios (estáticos) por esquema; cambiar de usuario (conectándose con cadenas de conexión coincidentes) sobre la marcha. –

1

Otra posibilidad es generar copias de cada SP en cada esquema, el nombre de la tabla no modificada en un SP se refiere a las tablas en el mismo esquema.

Nota esto no funciona con SQL dinámico dentro de un SP como:

CREATE PROCEDURE schema_a.SP 
    @somesql AS varchar(MAX) 
AS 
BEGIN 
    EXEC (@somesql) 
END 

CREATE PROCEDURE schema_b.SP 
    @somesql AS varchar(MAX) 
AS 
BEGIN 
    EXEC (@somesql) 
END 

no va a funcionar, porque la afinidad esquema se pierde en el interior del EXEC.

Si bien esto:

CREATE PROCEDURE schema_a.SP 
AS 
BEGIN 
    SELECT * FROM tbl -- Will use schema_a.tbl first 
END 

CREATE PROCEDURE schema_b.SP 
AS 
BEGIN 
    SELECT * FROM tbl -- Will use schema_b.tbl first 
END 

funciona bien.

mismo modo:

EXEC ('EXEC schema_a.SP') 

obviamente funcionar bien.

+0

Todavía un kludge, pero me gusta más que crear usuarios adicionales. –

+0

No funcionó. Cogió la mesa en dbo cuando lo probé. –

+0

Me gustaría ir con EXECUTE AS como en la respuesta de RBArryYoung ya que está usando SQL dinámico. La razón por la cual la afinidad de esquema no funciona para usted es que una vez que golpea al ejecutivo, está perdiendo el contexto del esquema del SP que llama a exec, al igual que pierde prácticamente todo lo demás. –

0

Sin probar, pero: ¿podría combinar los datos de los diferentes esquemas en una vista y agregar una columna que invoque el nombre del esquema?

CREATE VIEW AllPosts AS 
    SELECT Data1, Data2, 'Sept09' AS Partition FROM SO_Sept09..Posts 
    UNION ALL 
    SELECT Data1, Data2, 'Oct09' AS Partition FROM SO_Oct09..Posts 
    ... 

SELECT * FROM AllPosts WHERE Partition = 'Sept09' 
SELECT * FROM dbo.AllPosts('Sept09') -- if use table-valued function instead 
+0

Es un pensamiento, pero rompería mucho de mi indexación. –

+0

Puede indexar vistas, aunque con una gran cantidad de advertencias. http://msdn.microsoft.com/en-us/library/dd171921.aspx http://msdn.microsoft.com/en-us/library/ms191432.aspx –

11

Hay piezas de cómo hacer esto en varios lugares aquí, pero no del todo.La manera de hacer esto es:

  1. Hacer un usuario único inicio de sesión para cada esquema &

  2. Hacer estos usuarios los propietarios de cada esquema diferente.

  3. Establezca el esquema predeterminado de cada uno de esos usuarios como el esquema que poseen.

  4. Utilice la sintaxis EXECUTE ('sql commands') AS USER = 'schema-owner' para ejecutar sus comandos SQL en el contexto de ese esquema predeterminado.

La siguiente secuencia de comandos muestra esto:

--====== Create the Login for the User: 
CREATE LOGIN [UserTest1] WITH PASSWORD='whatever', DEFAULT_DATABASE=[TestUsers], DEFAULT_LANGUAGE=[us_english] 
GO 

--====== Make a User for the Login: 
CREATE USER [UserTest1] FOR LOGIN [UserTest1] 
GO 

--====== Make a Schema owned by the User and default to it: 
--  (I assume that you already have the schemas) 
CREATE SCHEMA [UserTest1] AUTHORIZATION [UserTest1] 
GO 
ALTER USER [UserTest1] WITH DEFAULT_SCHEMA=[UserTest1] 
GO 

--====== Make a sProc in dbo 
CREATE PROCEDURE [dbo].[TestSchema_Exec] AS 
    SELECT 'executing in schema [dbo]' 
GO 
--====== Make a similar sProc in New Schema 
CREATE PROCEDURE [UserTest1].[TestSchema_Exec] AS 
    SELECT 'executing in schema [UserTest1]' 
GO 

--========= Demonstrate that we can switch Default Schemas: 
EXEC('TestSchema_Exec') 

EXEC('TestSchema_Exec') AS USER = 'UserTest1' 
0

bien, tengo una nueva manera de hacer esto que podría funcionar un poco mejor para mí. Es una variante de mi comentario a la respuesta de Michael Petrotta:

Pero me da la idea de tal vez tener varios usuarios y elegir la cadena de conexión sobre la marcha.

Lo que haré es tener un solo usuario para ejecutar estas consultas, pero cambiaré la cadena de conexión sobre la marcha para especificar el Catálogo inicial correcto.

Cuestiones relacionadas