有没有一种方法可以持久保留变量?
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')
有关“ USE @bob”行,请参见此SO问题。
有没有一种方法可以持久保留变量?
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')
有关“ USE @bob”行,请参见此SO问题。
Answers:
该go
命令用于将代码拆分为单独的批处理。如果这正是您要执行的操作,则应使用它,但这意味着批次实际上是分开的,并且您不能在它们之间共享变量。
在您的情况下,解决方案很简单;您只需删除go
语句,该代码中就不需要它们。
注意:您不能在use
语句中使用变量,它必须是数据库的名称。
go
命令用于将代码拆分为单独的批处理。如果要这样做,则应该使用它,但这意味着批次实际上是分开的,并且您不能在它们之间共享变量。
使用临时表:
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
这样做还有一个好处,就是能够同时执行您原本想做的事情。
需要注意的是,您需要打开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
不确定,是否有帮助
declare @s varchar(50)
set @s='Northwind'
declare @t nvarchar(100)
set @t = 'select * from ' + @s + '.[dbo].[Customers]'
execute sp_executesql @t
临时表通过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
它不漂亮,但是可以用
创建自己的存储过程,将其保存/加载到临时表中。
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
如果只需要二进制“是/否”(例如是否存在列),则可以使用它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
这将编译语句,但不执行它们。因此,如果您引用不存在的架构,您仍然会遇到“编译错误”。因此,它可以“关闭”第二次运行的脚本(我在做什么),但无法在第一次运行时关闭脚本的某些部分,因为如果引用不这样做的列或表,您仍然会遇到编译错误还不存在。
您可以按照以下步骤使用NOEXEC:
建立表格
#temp_procedure_version(procedure_version varchar(5),pointer varchar(20))
将过程版本和指向该版本的指针插入到临时表中 #temp_procedure_version
--example procedure_version指针
插入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_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