如何在SQL Server中声明全局变量..?

Ume*_*dam 34 sql sql-server

我想对来自不同数据库的不同查询使用相同的值

喜欢

DECLARE @GLOBAL_VAR_1 INT = Value_1

DECLARE @GLOBAL_VAR_2 INT = Value_2

USE "DB_1"
GO
SELECT * FROM "TABLE" WHERE "COL_!" = @GLOBAL_VAR_1 

AND "COL_2" = @GLOBAL_VAR_2

USE "DB_2"
GO

SELECT * FROM "TABLE" WHERE "COL_!" = @GLOBAL_VAR_2 
Run Code Online (Sandbox Code Playgroud)

但它给出了错误.

必须声明标量变量"@GLOBAL_VAR_2".

任何人都可以提出任何方法来做到这一点......?

Lan*_*kin 32

无法在Transact-SQL中声明全局变量.但是,如果您希望所有变量都可以在单个脚本的批次中访问,则可以使用SQLCMD工具或SSMS 的SQLCMD模式,并定义特定于工具/模式的变量,如下所示:

:setvar myvar 10
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它们:

$(myvar)
Run Code Online (Sandbox Code Playgroud)

要使用SSMS的SQLCMD模式:

在此输入图像描述

  • @TomTom我上次会试试.StackOverflow的想法不是回答"不,它不可能",而是要说明如何做到这一点.无论"究竟"提出什么都没关系 - 人们不知道他们提出的问题的答案,所以他们需要周围的想法.奇怪的是你表现得如此拥有30k. (4认同)

Fed*_*jdu 15

无法在SQLServer中声明全局变量.

如果您正在使用Management Studio,则可以使用像@Lanorkin指出的SQLCMD模式.

否则,您可以使用CONTEXT_INFO存储在会话和连接期间可见的单个变量,但在此之后它将消失.

只有真正全局的才能创建一个全局临时表(名为## yourTableName),并将变量存储在那里,但是当所有连接都关闭时,它也会消失.

  • 实际上,我认为对于多个查询,正常的临时表也可以工作(而不是全局查询)。临时表的想法很整洁……在定义的参数范围内也是如此。 (2认同)
  • 如果在db脚本中创建数据库时创建了## yourTableName,那么它将保持不变(并且具有最少的日志记录) (2认同)

小智 9

你可以尝试一个全局表:

create table ##global_var
            (var1 int
            ,var2 int)

USE "DB_1"
GO
SELECT * FROM "TABLE" WHERE "COL_!" = (select var1 from ##global_var) 

AND "COL_2" = @GLOBAL_VAR_2

USE "DB_2"
GO

SELECT * FROM "TABLE" WHERE "COL_!" = (select var2 from ##global_var) 
Run Code Online (Sandbox Code Playgroud)


got*_*tqn 8

从开始SQL Server 2016的新途径共享会话信息通过引入SESSION_CONTEXTsp_set_session_context

您可以使用它们作为替代,CONTEXT_INFO()只保留限制为 128 字节的二进制值。此外,用户可以随时重写该值,将其用于安全检查不是很好。

使用新的实用程序解决了以下问题。您可以以更用户友好的格式存储数据:

EXEC sp_set_session_context 'language', 'English';  
SELECT SESSION_CONTEXT(N'language');
Run Code Online (Sandbox Code Playgroud)

此外,我们可以将其标记为read-only

EXEC sp_set_session_context 'user_id', 4, @read_only = 1;  
Run Code Online (Sandbox Code Playgroud)

如果您尝试修改read-only会话上下文,您将得到如下内容:

消息 15664,级别 16,状态 1,过程 sp_set_session_context,第 10 行无法在会话上下文中设置键“user_id”。此会话的密钥已设置为只读。


Rus*_*Fox 6

您可以通过创建返回变量值的标量值函数来获得类似的结果。当然,如果您在返回大量结果的查询中使用函数调用,函数调用可能会很昂贵,但如果您限制结果集,则应该没问题。在这里,我使用创建的数据库只是为了保存这些半静态值,但您也可以在每个数据库的基础上创建它们。如您所见,没有输入变量,只有一个返回静态值的命名良好的函数:如果您在函数中更改该值,它会在使用它的任何地方立即更改(下次调用时)。

USE [globalDatabase]
GO

CREATE FUNCTION dbo.global_GetStandardFonts ()
RETURNS NVARCHAR(255)
AS
BEGIN
    RETURN 'font-family:"Calibri Light","sans-serif";'
END
GO

--  Usage: 
SELECT '<html><head><style>body{' + globalDatabase.dbo.global_GetStandardFonts() + '}</style></head><body>...'

--  Result: <html><head><style>body{font-family:"Calibri Light","sans-serif";}</style></head><body>...
Run Code Online (Sandbox Code Playgroud)

  • 您可以将其设为内联函数以避免性能下降。 (2认同)

Sai*_*ini 6

尝试使用;而不是GO. 它适用于 2008 R2 版本

DECLARE @GLOBAL_VAR_1 INT = Value_1;

DECLARE @GLOBAL_VAR_2 INT = Value_2;

USE "DB_1";
SELECT * FROM "TABLE" WHERE "COL_!" = @GLOBAL_VAR_1 

AND "COL_2" = @GLOBAL_VAR_2;

USE "DB_2";

SELECT * FROM "TABLE" WHERE "COL_!" = @GLOBAL_VAR_2;
Run Code Online (Sandbox Code Playgroud)

  • 对于给定的示例,这是最佳解决方案。GO 语句终止当前批处理(以及任何已声明的局部变量),因此只要您可以在同一批处理中运行所有语句,就不需要它。 (2认同)