2011-03-23 21 views
22

Estoy intentando agrupar algunas secuencias de comandos SQL. En la parte superior he declarado algunas variables que considero global en el sentido del términoVariables globales con GO

Así:

DECLARE @someVar1 
DECLARE @someVar2 
...etc. 

GO 

Some batch of SQL here that sets @someVar1 and @SomeVar2 to a value and uses it in the SQL statement 

GO 


Some batch of SQL here that sets @someVar1 and @SomeVar2 to a value and uses it in the SQL statement 

GO 
... 

las declaraciones están fuera de alcance ... lo que significa cuando corro esto, el lote posterior los scripts no encuentran esas declaraciones. ¿Hay alguna manera de mantenerlos globales para todos los scripts por lotes que están utilizando o estableciendo estas variables para su uso?

Respuesta

21

Las tablas temporales hacen sobrevivir go 's:

create table #vars (someVar1 varchar(10), someVar2 int) 
insert #vars values ('abc',123) 

obtener el valor:

select someVar1 from #vars 

Valor seleccionado

update #vars set someVar1 = 'def' 

Las tablas temporales son específicos para su conexión, por lo que son no más globales de lo que deben ser.

+0

parece un montón de líneas, pero supongo que mucho mejor que duplicar las mismas definiciones de variables exactas en cada instrucción GO para establecerlas – PositiveGuy

+0

Me pregunto si la creación de una tabla temporal para simplemente contener globales es una forma ineficiente de hacer ¿¿cosas?? Quiero decir que estás creando una nueva entidad de tabla por el hecho de mantener vars globales ... no estoy seguro de que – PositiveGuy

+0

haya insertado valores predeterminados y luego los hayas configurado/actualizado. No tengo valores predeterminados para establecer aquí – PositiveGuy

4

No hay tal cosa como una variable global, pero se puede hacer algo como esto: ejemplo Link

Uso:

EXEC sp_SetGlobalVariableValue 'Test1', 'test1' 
EXEC sp_SetGlobalVariableValue 'Test2', 'test2' 

GO 

EXEC sp_GetGlobalVariableValue 'Test1' 
EXEC sp_GetGlobalVariableValue 'Test2' 

GO 

EXEC sp_GetGlobalVariableValue 'Test1' 
EXEC sp_GetGlobalVariableValue 'Test2' 

GO 

Usando los procedimientos almacenados mencionadas en el enlace de arriba, yo era capaz de establecer variables globales y hacer que duren entre GO.

+0

gracias supongo que debería haber mirado las variables globales. Encontré esto en msdn "Los nombres de algunas funciones del sistema Transact-SQL comienzan con dos en signos (@@). Aunque en versiones anteriores de Microsoft SQL Server, las funciones @@ se conocen como variables globales, no son variables y no no tienen los mismos comportamientos que las variables. Las funciones @@ son funciones del sistema, y ​​su uso de sintaxis sigue las reglas para las funciones ". – PositiveGuy

+0

entonces ... No sé si realmente es compatible, esto está diciendo que no actúa como una variable y que son funciones del SISTEMA según este artículo: http://msdn.microsoft.com/en-us/library /ms187953.aspx – PositiveGuy

+0

e incluso si arrojo estas definiciones de variables en un proceso almacenado, aún no las veo en cada instrucción GO – PositiveGuy

2

Las variables se van fuera de alcance porque el GO statement señala el final del lote. La documentación tema Microsoft Transact-SQL Variables tiene este ejemplo:

El alcance de una variable dura desde el punto es declarado hasta el final del lote o procedimiento almacenado en el que es declarado. Por ejemplo, el siguiente secuencia de comandos genera un error de sintaxis porque la variable se declara en un lote y se hace referencia en otro:

USE AdventureWorks2008R2; 
GO 
DECLARE @MyVariable int; 
SET @MyVariable = 1; 
-- Terminate the batch by using the GO keyword. 
GO 
-- @MyVariable has gone out of scope and no longer exists. 

-- This SELECT statement generates a syntax error because it is 
-- no longer legal to reference @MyVariable. 
SELECT BusinessEntityID, NationalIDNumber, JobTitle 
FROM HumanResources.Employee 
WHERE BusinessEntityID = @MyVariable; 

Creo que lo que quiere hacer es crear una tabla temporal para almacenar su "variables globales. Vea la respuesta de Andomar para un ejemplo de cómo hacer eso. Él tiene una variable por fila. También veo tablas temporales que tienen una columna para cada variable global deseada y solo una fila se inserta en la tabla. Esto permite que cada variable tenga un tipo de datos diferente.

+0

Sí, lo había leído antes de esta publicación. Ah, buena información sobre la mesa temporal. Gracias. – PositiveGuy

4

Es posible que no necesite utilizar lotes, en cuyo caso puede conseguir que sus variables sobrevivan durante mucho tiempo.No estoy seguro si esto es la mejor práctica, pero por ejemplo una declaración de función por lo general tendría que ser la única instrucción en un lote de este modo:

Declare @batch_scope_var INT 
GO --This is required 

CREATE FUNCTION dbo.Half(@function_scope_var int) 
RETURNS int 
WITH EXECUTE AS CALLER 
AS 
BEGIN 
    RETURN @function_scope_var/2 
END 
GO --This is required 

SET @batch_scope_var = 4 --Bugger, this is now out of scope and won't execute! 
print dbo.Half(@batch_scope_var) 
GO 

Sin embargo puede volver a escribir esta usando * sp_executesql * y evitar todos los lotes de este modo:

Declare @batch_scope_var INT 

execute dbo.sp_executesql @statement = N' 
CREATE FUNCTION dbo.Half(@function_scope_var int) 
RETURNS int 
WITH EXECUTE AS CALLER 
AS 
BEGIN 
    RETURN @function_scope_var/2 
END 
' 

SET @batch_scope_var = 4 
print dbo.Half(@batch_scope_var) 
GO 

realmente depende de la complejidad de su escritura en cuanto a si usted quiere hacer esto, ya que puede ser un poco desordenado y se pierde usted resaltado de sintaxis tan pronto como todo lo está en una cadena gigante :)

10

Puede declarar variables de scripting, que se pueden definir explícitamente mediante el uso del comando setvar y no salir de alcance en la instrucción GO.

p. Ej.

--Declare the variable 
:setvar MYDATABASE master 
--Use the variable 
USE $(MYDATABASE); 
SELECT * FROM [dbo].[refresh_indexes] 
GO 
--Use again after a GO 
SELECT * from $(MYDATABASE).[dbo].[refresh_indexes]; 
GO 

Para más información ir a: http://technet.microsoft.com/en-us/library/ms188714.aspx

+0

Si desea que este valor se trate como una cadena, debe adjuntar el uso o la declaración entre comillas simples (pero no ambas). p.ej. ': setvar EchoMe MyDB \ ngo \ nselect '$ (EchoMe)' 'funciona igual que': setvar EchoMe' MyDB '\ ngo \ nselect $ (EchoMe) '. Sin una comilla simple ('''') encuentra 'Nombre de columna inválido 'MyDB'. Con ambos comillas simples se obtiene 'Se encontró sintaxis incorrecta al analizar: setvar.' Si su valor tiene espacios, debe hacer una comilla doble en la declaración y comillas simples ya sea en la declaración o en la instrucción SELECT. (al menos en el Servidor 2008R2) – mpag

+0

Desafortunadamente, no está permitido cambiar estas variables en el script PostDeployment de SSDT. Todas las asignaciones se mueven a la parte superior del scrip automáticamente. –