94

有没有办法在整个过程中保持一个变量?

Declare @bob as varchar(50);
Set @bob = 'SweetDB'; 
GO
USE @bob  --- see note below
GO
INSERT INTO @bob.[dbo].[ProjectVersion] ([DB_Name], [Script]) VALUES (@bob,'1.2')

有关“使用@bob”行,请参阅此SO问题。

4

9 回答 9

143

使用临时表:

CREATE TABLE #variables
(
    VarName VARCHAR(20) PRIMARY KEY,
    Value VARCHAR(255)
)
GO

Insert into #variables Select 'Bob', 'SweetDB'
GO

Select Value From #variables Where VarName = 'Bob'
GO

DROP TABLE #variables
go
于 2009-06-02T05:14:50.007 回答
35

go命令用于将代码拆分为单独的批次。如果这正是您想要做的,那么您应该使用它,但这意味着批次实际上是分开的,并且您不能在它们之间共享变量。

在您的情况下,解决方案很简单;您可以删除go语句,该代码中不需要它们。

旁注:您不能在use语句中使用变量,它必须是数据库的名称。

于 2009-06-02T00:08:29.580 回答
17

我更喜欢这个问题Global Variables with GO的这个答案

这还有一个额外的好处,就是能够做你最初想做的事情。

需要注意的是,您需要打开 SQLCMD 模式(在 Query->SQLCMD 下)或默认为所有查询窗口打开它(工具->选项然后查询结果->默认情况下,在 SQLCMD 模式下打开新查询)

然后您可以使用以下类型的代码(完全从Oscar E. Fraxedas Tormo的相同答案中抄袭)

--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
于 2015-06-18T06:39:31.713 回答
4

如果您使用的是 SQL Server,您可以为整个脚本设置全局变量,例如:

:setvar sourceDB "lalalallalal"

稍后在脚本中使用:

$(sourceDB)

确保 SQLCMD 模式在 Server Managment Studi 中打开,您可以通过顶部菜单单击 Query 并打开 SQLCMD 模式。

可以在此处找到有关该主题的更多信息: MS 文档

于 2017-08-31T09:35:59.097 回答
1

临时表保留在 GO 语句上,所以......

SELECT 'value1' as variable1, 'mydatabasename' as DbName INTO #TMP

-- get a variable from the temp table
DECLARE @dbName VARCHAR(10) = (select top 1 #TMP.DbName from #TMP)
EXEC ('USE ' + @dbName)
GO

-- get another variable from the temp table
DECLARE @value1 VARCHAR(10) = (select top 1 #TMP.variable1 from #TMP)

DROP TABLE #TMP

它不漂亮,但它有效

于 2017-09-18T09:03:17.993 回答
1

创建您自己的存储过程,将其保存/加载到临时表。

MyVariableSave   -- Saves variable to temporary table. 
MyVariableLoad   -- Loads variable from temporary table.

然后你可以使用这个:

print('Test stored procedures for load/save of variables across GO statements:')

declare @MyVariable int = 42
exec dbo.MyVariableSave @Name = 'test', @Value=@MyVariable
print('  - Set @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))

print('  - GO statement resets all variables')
GO -- This resets all variables including @MyVariable

declare @MyVariable int
exec dbo.MyVariableLoad 'test', @MyVariable output
print('  - Get @MyVariable = ' + CAST(@MyVariable AS VARCHAR(100)))

输出:

Test stored procedures for load/save of variables across GO statements:
  - Set @MyVariable = 42
  - GO statement resets all variables
  - Get @MyVariable = 42

您还可以使用这些:

exec dbo.MyVariableList       -- Lists all variables in the temporary table.
exec dbo.MyVariableDeleteAll  -- Deletes all variables in the temporary table.

输出exec dbo.MyVariableList

Name    Value
test    42

事实证明,能够列出表中的所有变量实际上非常有用。因此,即使您稍后不加载变量,也非常适合调试目的,以便在一个地方查看所有内容。

这使用了一个带有##前缀的临时表,因此它足以在 GO 语句中存活。它旨在在单个脚本中使用。

和存储过程:

-- Stored procedure to save a variable to a temp table.
CREATE OR ALTER PROCEDURE MyVariableSave 
    @Name varchar(255),
    @Value varchar(MAX)
WITH EXECUTE AS CALLER
AS  
BEGIN
    SET NOCOUNT ON
    IF NOT EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        DROP TABLE IF EXISTS ##VariableLoadSave
        CREATE TABLE ##VariableLoadSave
        (
            Name varchar(255),
            Value varchar(MAX)
        )
    END
    UPDATE ##VariableLoadSave SET Value=@Value WHERE Name=@Name
    IF @@ROWCOUNT = 0
        INSERT INTO ##VariableLoadSave SELECT @Name, @Value
END
GO
-- Stored procedure to load a variable from a temp table.
CREATE OR ALTER PROCEDURE MyVariableLoad 
    @Name varchar(255),
    @Value varchar(MAX) OUT
WITH EXECUTE AS CALLER
AS  
BEGIN
    IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        IF NOT EXISTS(SELECT TOP 1 * FROM ##VariableLoadSave WHERE Name=@Name)
        BEGIN
            declare @ErrorMessage1 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
            raiserror(@ErrorMessage1, 20, -1) with log
        END

        SELECT @Value=CAST(Value AS varchar(MAX)) FROM ##VariableLoadSave
        WHERE Name=@Name
    END
    ELSE
    BEGIN
        declare @ErrorMessage2 as varchar(200) = 'Error: cannot find saved variable to load: ' + @Name
        raiserror(@ErrorMessage2, 20, -1) with log
    END
END
GO
-- Stored procedure to list all saved variables.
CREATE OR ALTER PROCEDURE MyVariableList
WITH EXECUTE AS CALLER
AS  
BEGIN
    IF EXISTS (select TOP 1 * from tempdb.sys.objects where name = '##VariableLoadSave')
    BEGIN
        SELECT * FROM ##VariableLoadSave
        ORDER BY Name
    END
END
GO
-- Stored procedure to delete all saved variables.
CREATE OR ALTER PROCEDURE MyVariableDeleteAll
WITH EXECUTE AS CALLER
AS  
BEGIN
    DROP TABLE IF EXISTS ##VariableLoadSave
    CREATE TABLE ##VariableLoadSave
    (
        Name varchar(255),
        Value varchar(MAX)
    )
END
于 2019-04-06T09:19:35.057 回答
0

不确定,如果这有帮助

declare @s varchar(50)
set @s='Northwind'

declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'

execute sp_executesql @t
于 2009-06-02T00:23:20.503 回答
0

如果您只需要二进制是/否(例如是否存在列),则可以使用SET NOEXEC ON来禁用语句的执行。 SET NOEXEC ON跨 GO(跨批次)工作。但请记住在脚本末尾重新打开 EXEC 。SET NOEXEC OFF

IF COL_LENGTH('StuffTable', 'EnableGA') IS NOT NULL
    SET NOEXEC ON -- script will not do anything when column already exists

ALTER TABLE dbo.StuffTable ADD EnableGA BIT NOT NULL CONSTRAINT DF_StuffTable_EnableGA DEFAULT(0)
ALTER TABLE dbo.StuffTable SET (LOCK_ESCALATION = TABLE)
GO
UPDATE dbo.StuffTable SET EnableGA = 1 WHERE StuffUrl IS NOT NULL
GO
SET NOEXEC OFF

这编译语句但不执行它们。因此,如果您引用不存在的架构,您仍然会收到“编译错误”。所以它可以“关闭”第二次运行的脚本(我正在做的事情),但不能在第一次运行时关闭部分脚本,因为如果引用列或表,你仍然会遇到编译错误还不存在。

于 2019-06-07T19:35:22.977 回答
0

您可以按照以下步骤使用 NOEXEC:

创建表

#temp_procedure_version(procedure_version varchar(5),pointer varchar(20))

将过程版本和指向版本的指针插入到临时表中#temp_procedure_version

--example 过程版本指针

插入temp_procedure_version值(1.0,'第一个版本')

插入temp_procedure_version值(2.0,'最终版本')

然后检索过程版本,您可以使用 where 条件,如以下语句

@ProcedureVersion=ProcedureVersion#temp_procedure_version哪里 选择pointer='first version'

IF (@ProcedureVersion='1.0')
    BEGIN
    SET NOEXEC OFF  --code execution on 
    END
ELSE
    BEGIN 
    SET NOEXEC ON  --code execution off
    END 

--在此处插入程序版本 1.0

创建过程版本 1.0 为.....

SET NOEXEC OFF -- execution is ON

@ProcedureVersion=ProcedureVersion#temp_procedure_versionwhere pointer='final version' 中选择

IF (@ProcedureVersion='2.0')
    BEGIN
    SET NOEXEC OFF  --code execution on 
    END
ELSE
    BEGIN 
    SET NOEXEC ON  --code execution off
    END 

创建过程版本 2.0 为.....

SET NOEXEC OFF -- execution is ON

--删除临时表

删除表#temp_procedure_version

于 2019-09-17T08:11:01.423 回答