2010-01-26 6 views
4

Допустим, я хотел создать SQL-скрипт и сделать что-то вроде этого:Глобальные переменные в SQL

DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 
--do stuff with @SomeVariable 
GO 

CREATE PROCEDURE myProcedure 
(
    @MyParameter 
) 
AS 
SET NOCOUNT ON 

--Do something 
--Do something using @SomeVariable 
SET NOCOUNT OFF 
RETURN 0 
GO 

я не могу, потому что @SomeVariable умирает с партии он принадлежит, и myProcedure требует своей собственной партия. Очевидно, я мог бы создать таблицу #temp и понаблюдать за любыми значениями, которые мне нужны, но тогда мне нужно будет выбрать из нее - добавление кода, который, хотя и тривиальный, имеет больший читабельности и кажется глупым, когда все, что мне нужно, - это глобальная переменная. Есть ли способ лучше?

Должно быть болезненно ясно. Я ЗНАЮ SQL Server имеет «глобальные переменные», называемые «таблицами». Я упомянул в предыдущем абзаце, что использование # таблицы является возможным решением, так как используется фактическая постоянная таблица. То, что я ищу здесь, вероятно, является большей частью глобальной константы, которую я могу использовать в любом месте внутри данного сценария, а не глобальной переменной, поэтому мы все можем перестать смазывать наши штаны о зле глобальных переменных.

+1

О мальчик, что катится мир. ? :( – ChaosPandion

+1

Что вы делаете, что требует глобального переменного Если бы мы знали больше, мы могли бы предоставить альтернативные –

+0

Просто чтобы быть ясно, что вы ищете глобальные переменный или глобальную константу – JohnFx

ответ

4

Непонятно, почему хранимая процедура имеет зависимость от вашего глобального в вашем примере набора из двух партий. Я вижу две основные возможности: либо SP имеет зависимость от глобального в момент создания (например, генерация кода - случай 1), либо у SP есть зависимость времени выполнения от глобального (т. Е. Вы должны выбрать между параметризацией - случай 2 - или самоконфигурация - Case3).

В случае выполнения зависимости, будь то получается из некоторого места вне SP и передается в качестве параметра или внутри SP непосредственно является основным проектным решением. Выбор того, когда передавать данные в качестве параметра и когда вытягивать из таблиц - это не совсем наука, все зависит от всех случаев использования в реальной жизни в системе.

Случай 1 - Генерация кода:

DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 
--do stuff with @SomeVariable 
GO 

DECLARE @sp as varchar(MAX) 

SET @sp = ' 
CREATE PROCEDURE myProcedure -- I would actually name this myProcedure_ + CONVERT(varchar, @SomeVariable), since each proc generated might function differently 
( 
    @MyParameter 
) 
AS 
SET NOCOUNT ON 
DECLARE @SomeVariable AS int -- This is going to be an initialized local copy of the global at time of SP creation 
SET @SomeVariable = ' + CONVERT(varchar, @SomeVariable) + ' 

--Do something 
--Do something using @SomeVariable 
SET NOCOUNT OFF 
RETURN 0 
' 
EXEC(@sp) -- create the procedure dynamically 

Executing the producedure normally as EXEC myProcedure or EXEC myProcedure_1, etc. 

Случай 2 - Параметризация:

DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 
--do stuff with @SomeVariable 
GO 

CREATE PROCEDURE myProcedure 
( 
    @MyParameter 
    ,@SomeVariable int 
) 
AS 
SET NOCOUNT ON 

--Do something 
--Do something using @SomeVariable 
SET NOCOUNT OFF 
RETURN 0 
GO 

Теперь, когда myProcedure называется, он всегда должен быть передан параметр @SomeVariable. Это рекомендуется, если вы вызываете же SP с различной параметризацией регулярно

Случая 3 - Конфигурация:

DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 
--do stuff with @SomeVariable 
GO 

CREATE PROCEDURE myProcedure 
( 
    @MyParameter 
) 
AS 
SET NOCOUNT ON 

--Do something 
DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 

SET NOCOUNT OFF 
RETURN 0 
GO 

Теперь, когда вы EXEC myProcedure, вам необходимо убедиться, что конфигурация была установлена ​​в таблице , Этот сценарий рекомендуется для медленно меняющихся конфигурационных случаев. В этом случае, вы можете обернуть @SomeVariable инициализации в скалярной UDF, так что любые времена эта же конфигурация используется в различных ЗЛ, все они будут вызов через тот же UDF, который освобождает вас изменить ваши настройки условности таблицы (вы не давайте своим пользователям разрешение SELECT на ваших таблицах, так или иначе?), и если UDF должен начать меняться в зависимости от пользователя или аналогичного, теперь у вас есть контрольная точка, которая обеспечивает согласованность, разрешения и соглашения о вызовах интерфейса:

DECLARE @SomeVariable int 
SET @SomeVariable = dbo.udf_Global(username, session, etc.) 
--do stuff with @SomeVariable 
GO 

CREATE PROCEDURE myProcedure 
( 
    @MyParameter 
) 
AS 
SET NOCOUNT ON 

--Do something 
DECLARE @SomeVariable int 
SET @SomeVariable = dbo.udf_Global(username, session, etc.) 

SET NOCOUNT OFF 
RETURN 0 
GO 
+1

Я думаю, что решение таблицы, вероятно, так и будет в этом случае, но динамическое объявление хранимой процедуры - это гладкая идея, и я ценю ваш чрезвычайно тщательный анализ моего вопроса. Я принимаю этот ответ из-за того, насколько хорошо продуман и объяснил это. – Zannjaminderson

+0

Я не думаю, что мы действительно достаточно поняли о вашей системе, почему вы делали эти совершенно разные типы партий в порядке. Как правило, хранимые процедуры являются долговременной частью базы данных и не будут изменяться очень часто. –

5

Оператор GO, который не является частью спецификации языка SQL, является разделителем пакетов. Ваши локальные переменные привязаны к пакету. Таким образом, они выходят за пределы поля в заявлении GO. Я думаю, что ваша единственная альтернатива - это то, что вы описали.

+0

Ох ... Я думал, что «GO» был просто вежливым запросом для агрегированных сценариев, чтобы продолжать работать нормально. +1 – iandisme

+1

Да, суть этой проблемы в том, что - как мы можем сохранить некоторую ценность, где мы можем использовать ее через партии, не набирая ее в таблицу. Я подумал, что посмотрю, есть ли другой способ, но, похоже, нет. – Zannjaminderson

1

Если вы после некоторого глобального постоянного значения, которое могут использовать несколько различных процедур, то сохранение его в таблице - это лучшее, что я могу придумать.

Если вы хотите, чтобы переменная, которую вы используете в рамках одной процедуры, несколько раз, вы включаете ее в определение процедуры.

CREATE PROCEDURE myProcedure 
( 
    @MyParameter 
) 
AS 
SET NOCOUNT ON 

DECLARE @SomeVariable int 
SET @SomeVariable = 'VALUE' 
    FROM someTable 
--do stuff with @SomeVariable 

--Do something 
--Do something using @SomeVariable 
SET NOCOUNT OFF 
RETURN 0 
GO 

И если вы хотите какую-то хорошая инкапсуляцию логики, вы можете ссылаться в удобном виде, то скалярная функция пользователя (UDF) может быть то, что вы после этого.

0

Глобальная переменная - это плохая практика на любом языке программирования. Почему бы просто не передать переменную в качестве параметра хранимой процедуры.

CREATE PROCEDURE myProcedure 
(
    @MyParameter, 
    @SomeVariable -- the global variable 
) 
AS 
... 
+1

Неправда. Глобалы и их друзья-ОО «статика» имеют много действительных применений. Вам просто нужно закодировать код. – roufamatic

0

Как насчет создания таблицы под названием что-то вроде dbo.Configuration, который вы можете хранить кучу ценностей, вытаскивая их, когда вам нужно? Это будет максимум одна или две страницы, поэтому быстрый доступ, вероятно, остался в ОЗУ все время, и вы можете погрузиться в него из любого места.

1

Я думаю, что нам нужно немного больше контекста, поскольку я не вижу здесь смысла, но я могу дать вам немного понимания, основываясь на том, что я знаю.

У вас есть две разные партии, одна из которых является обычным блоком кода, а другая, которая на самом деле ничего не делает, кроме создания хранимой процедуры.

Если вам нужна хранимая процедура, с которой нужно работать, просто введите ее.

Если вам нужно поделиться приведенным выше значением с хранимыми процедурами, потенциально вы можете использовать скалярную функцию, чтобы вернуть требуемое значение по требованию.

Смежные вопросы