Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL中的全局变量_Sql_Sql Server - Fatal编程技术网

SQL中的全局变量

SQL中的全局变量,sql,sql-server,Sql,Sql Server,假设我想创建一个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 NO

假设我想创建一个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需要自己的批。显然,我可以创建一个临时表,并在其中填充我需要的任何值,但我必须从中进行选择—添加代码,虽然很琐碎,但会损害可读性,而且当我只需要一个全局变量时,这看起来很愚蠢。有更好的办法吗


非常清楚。我知道SQL Server有一个称为表的全局变量——我在上面一段中提到,使用表是一种可能的解决方案,就像使用实际的永久表一样。我在这里寻找的可能更多的是一个全局常量,我可以在给定脚本中的任何地方使用它,而不是一个全局变量-因此我们都可以不再为全局变量的罪恶而沾沾自喜。

GO语句不是SQL语言规范的一部分,它是一个批处理分隔符。局部变量的作用域为批处理。因此,它们在go语句中超出了范围。我认为您唯一的选择是与您所描述的内容类似的内容。

如果您想要多个不同过程可以使用的全局持久值,那么将其存储在表中是我能想到的最好方法

如果只需要在单个过程中多次使用的变量,则可以将其包含在过程定义中

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就是你想要的。

全局变量在任何编程语言中都是不好的做法。为什么不将变量作为参数传递到存储过程中呢

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

创建一个名为dbo.Configuration的表怎么样,您可以在其中存储一组值,并在需要时将它们取出?最多只有一到两页,访问速度很快,可能一直留在RAM中,你可以从任何地方浏览。

我想我们需要更多的上下文,因为我不太明白这一点,但我可以根据我所知道的,给你一些见解

这里有两个不同的批处理,一个只是一个常规代码块,另一个实际上不做任何事情,而是创建一个存储过程

CREATE PROCEDURE myProcedure
(
  @MyParameter,
  @SomeVariable  -- the global variable
)
AS
...
如果需要使用存储过程中的值,只需将其作为输入即可


如果需要跨存储过程共享上述值,则可以使用标量函数按需返回所需的值。

不清楚为什么存储过程在两个批处理的示例集中依赖于全局值。我看到了两种主要的可能性:SP在创建时依赖于全局,即代码生成(案例1),或者SP在运行时依赖于全局,即您必须在参数化(案例2)或自配置(案例3)之间进行选择

对于运行时依赖关系,基本设计决策是从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 
现在,无论何时执行myProcedure,都需要确保已在表中设置了配置。对于缓慢变化的配置情况,建议使用此方案。在这种情况下,您可以将@SomeVariable初始化封装在标量值UDF中,以便在不同SP中使用相同配置时,它们都将通过相同的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 

哦,孩子,世界将要变成什么样子你在做什么,需要一个全局变量?如果我们知道更多,我们可以提供替代方案。SQL Server确实有全局变量-它们被称为表。这正是创建临时表的目的。克服它,使用它们。停止尝试在SQL中编写C。好吧,我会接受对snide的一两次否决票,但是没有人看到改进的可读性和可写性,这可能来自于能够引用常量,而不是每次使用时都从表或临时表中选择值。哦。。。我认为GO只是一个礼貌的请求,要求聚合脚本继续正常运行+1.
是的,这个问题的关键是——我们如何保持一些价值,我们可以跨批次使用它,而不只是将其填入表中。我想我会看看是否有其他的方法,但遗憾的是,似乎没有。Globals及其OO好友statics有很多有效的用途。您只需要防御性地编写代码。我认为表解决方案可能是我在本例中仍然会采用的方式,但存储过程的动态声明是一个巧妙的想法,我感谢您对我的问题进行的极其透彻的分析。我之所以接受这个答案,是因为它是经过深思熟虑和解释的。我认为我们对您的系统了解得不够,无法理解您为什么要按顺序进行这些完全不同类型的批次。通常,存储过程是数据库的长期组成部分,不会频繁更改。