如何在 T-SQL 脚本中声明跨多个脚本通用的变量 运行
How to declare variables in T-SQL scripts that are common across multiple scripts being run
我有一组脚本来执行批量数据导入,我试图将它们包含在使用 SqlCmd 模式的单个 'calling' 脚本中。我遇到的问题是每个脚本都包含同一组定义路径或公共对象的已声明变量。当我 运行 'calling' 脚本时,我得到了变量已经被声明的错误。
如果我从各个脚本中提取声明,Intellisense 会抱怨它们没有声明。脚本本身也需要 运行 与 'calling' 脚本隔离开来,因此理想情况下我需要在各个脚本中也声明变量。
谢谢。
例子:
通用的单个脚本声明和初始 SET
DECLARE @path varchar(256),
@currPeriod varchar(25),
@pastPeriod varchar(25),
@period varchar(25),
@fileName varchar(256),
@sheet varchar(25),
@sql varchar(MAX)
SET @path = 'H:\Scripts\DataImport';
SET @currPeriod = CONCAT(DATEPART(year,GETDATE()),'-',CONVERT(varchar(2), getdate(), 101));
SET @pastPeriod = CONCAT(DATEPART(year,DateAdd(month, -1, Convert(date, GETDATE()))),'-',CONVERT(varchar(2), DateAdd(month, -1, Convert(date, GetDate())), 101));
SET @period = @pastPeriod; -- Change to currPeriod or pastPeriod based on import type.
SET @fileName = 'ReferenceClients-' + @period + '.xlsx';
SET @sheet = '[Sheet1$]';
SET @sql = 'INSERT INTO #TempRefClients
SELECT *
FROM OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',
''Excel 12.0; Database=' + @path + '\' + @period + '\' + @fileName + '; HDR=YES; IMEX=1'',
''SELECT * FROM ' + @sheet + ''')'
调用脚本示例 - 运行 使用 SqlCmd 模式
-- Ref Clients
BEGIN
PRINT ' ';
PRINT 'Importing Ref Clients';
:r "H:\Scripts\DataImport\CurrentMonthScripts\BulkImport-RefClients.sql"
END;
-- Top Clients
BEGIN
PRINT ' ';
PRINT 'Importing Top Clients';
:r "H:\Scripts\DataImport\CurrentMonthScripts\BulkImport-TopClients.sql"
END;
您应该可以通过做三件事来完成此任务:
不要在主脚本中声明变量。相反,创建一个本地临时 table:
CREATE TABLE #ConfigSettings
(
[SomePath] NVARCHAR(500) NOT NULL,
[CommonObjectA] NVARCHAR(128) NOT NULL,
[SomeMaxValue] INT
);
INSERT INTO #ConfigSettings VALUES (N'C:\go\here\for\some\reason\', N'objectName', 55);
在每个包含的脚本中,也需要与主脚本分开运行,在变量名称的末尾使用脚本 ID 声明变量,以便它们可以单独存在或与其他脚本的变量一起存在:
DECLARE @SomePath_1 NVARCHAR(500) = N'default_when_run_individually',
@CommonObjectA_1 NVARCHAR(128) = N'default_value',
@SomeMaxValue_1 INT = default_value;
另一个脚本将具有:
DECLARE @SomePath_2 NVARCHAR(500) = N'default_when_run_individually',
@CommonObjectA_2 NVARCHAR(128) = N'default_value',
@SomeMaxValue_2 INT = default_value;
在每个脚本中声明变量后,根据本地临时文件中的值设置它们table:
IF (OBJECT_ID(N'tempdb..#ConfigSettings') IS NOT NULL)
BEGIN
SELECT @SomePath_1 = cnf.[SomePath],
@CommonObjectA_1 = cnf.[CommonObjectA],
@SomeMaxValue_1 = cnf.[SomeMaxValue]
FROM #ConfigSettings cnf
END;
当每个脚本单独 运行 时,变量将保留其默认值。当它们在主脚本中 运行 时,本地温度 table 将存在并将覆盖这些默认值。
或
同样,不要在主脚本中声明任何东西,即使是本地临时文件 table 来保存配置值。
创建一个要通过 :r
读取的包含文件,设置所有 SQLCMD 变量:
:setvar SomePath "C:\go\here\for\some\reason\"
:setvar CommonObject "objectName"
:setvar SomeMaxValue 55
在每个脚本的顶部,读入该公共包含文件:
:r C:\AppConfigStuff\CommonIncludeConfigVariables.sql
在每个包含的脚本中,也需要与主脚本分开运行,在变量名称的末尾使用脚本 ID 声明变量,以便它们可以单独存在或与其他脚本的变量一起存在,并使用 SQLCMD 变量作为默认值:
DECLARE @SomePath_1 NVARCHAR(500) = N'$(SomePath)',
@CommonObjectA_1 NVARCHAR(128) = N'$(CommonObject)',
@SomeMaxValue_1 INT = $(SomeMaxValue);
另一个脚本将具有:
DECLARE @SomePath_2 NVARCHAR(500) = N'$(SomePath)',
@CommonObjectA_2 NVARCHAR(128) = N'$(CommonObject)',
@SomeMaxValue_2 INT = $(SomeMaxValue);
在这两种方法中,在每个单独的脚本中使用唯一的变量名将消除任何冲突,尤其是当您有其他原因不在脚本之间放置 "GO" 语句时。
并且,在第二种方法中,如果将所有 T-SQL 变量引用替换为SQLCMD 变量引用(例如 = $(IntVar)
或 = N'$(StringVar)'
)。
我有一组脚本来执行批量数据导入,我试图将它们包含在使用 SqlCmd 模式的单个 'calling' 脚本中。我遇到的问题是每个脚本都包含同一组定义路径或公共对象的已声明变量。当我 运行 'calling' 脚本时,我得到了变量已经被声明的错误。
如果我从各个脚本中提取声明,Intellisense 会抱怨它们没有声明。脚本本身也需要 运行 与 'calling' 脚本隔离开来,因此理想情况下我需要在各个脚本中也声明变量。
谢谢。
例子: 通用的单个脚本声明和初始 SET
DECLARE @path varchar(256),
@currPeriod varchar(25),
@pastPeriod varchar(25),
@period varchar(25),
@fileName varchar(256),
@sheet varchar(25),
@sql varchar(MAX)
SET @path = 'H:\Scripts\DataImport';
SET @currPeriod = CONCAT(DATEPART(year,GETDATE()),'-',CONVERT(varchar(2), getdate(), 101));
SET @pastPeriod = CONCAT(DATEPART(year,DateAdd(month, -1, Convert(date, GETDATE()))),'-',CONVERT(varchar(2), DateAdd(month, -1, Convert(date, GetDate())), 101));
SET @period = @pastPeriod; -- Change to currPeriod or pastPeriod based on import type.
SET @fileName = 'ReferenceClients-' + @period + '.xlsx';
SET @sheet = '[Sheet1$]';
SET @sql = 'INSERT INTO #TempRefClients
SELECT *
FROM OPENROWSET(''Microsoft.ACE.OLEDB.12.0'',
''Excel 12.0; Database=' + @path + '\' + @period + '\' + @fileName + '; HDR=YES; IMEX=1'',
''SELECT * FROM ' + @sheet + ''')'
调用脚本示例 - 运行 使用 SqlCmd 模式
-- Ref Clients
BEGIN
PRINT ' ';
PRINT 'Importing Ref Clients';
:r "H:\Scripts\DataImport\CurrentMonthScripts\BulkImport-RefClients.sql"
END;
-- Top Clients
BEGIN
PRINT ' ';
PRINT 'Importing Top Clients';
:r "H:\Scripts\DataImport\CurrentMonthScripts\BulkImport-TopClients.sql"
END;
您应该可以通过做三件事来完成此任务:
不要在主脚本中声明变量。相反,创建一个本地临时 table:
CREATE TABLE #ConfigSettings ( [SomePath] NVARCHAR(500) NOT NULL, [CommonObjectA] NVARCHAR(128) NOT NULL, [SomeMaxValue] INT ); INSERT INTO #ConfigSettings VALUES (N'C:\go\here\for\some\reason\', N'objectName', 55);
在每个包含的脚本中,也需要与主脚本分开运行,在变量名称的末尾使用脚本 ID 声明变量,以便它们可以单独存在或与其他脚本的变量一起存在:
DECLARE @SomePath_1 NVARCHAR(500) = N'default_when_run_individually', @CommonObjectA_1 NVARCHAR(128) = N'default_value', @SomeMaxValue_1 INT = default_value;
另一个脚本将具有:
DECLARE @SomePath_2 NVARCHAR(500) = N'default_when_run_individually', @CommonObjectA_2 NVARCHAR(128) = N'default_value', @SomeMaxValue_2 INT = default_value;
在每个脚本中声明变量后,根据本地临时文件中的值设置它们table:
IF (OBJECT_ID(N'tempdb..#ConfigSettings') IS NOT NULL) BEGIN SELECT @SomePath_1 = cnf.[SomePath], @CommonObjectA_1 = cnf.[CommonObjectA], @SomeMaxValue_1 = cnf.[SomeMaxValue] FROM #ConfigSettings cnf END;
当每个脚本单独 运行 时,变量将保留其默认值。当它们在主脚本中 运行 时,本地温度 table 将存在并将覆盖这些默认值。
或
同样,不要在主脚本中声明任何东西,即使是本地临时文件 table 来保存配置值。
创建一个要通过
:r
读取的包含文件,设置所有 SQLCMD 变量::setvar SomePath "C:\go\here\for\some\reason\" :setvar CommonObject "objectName" :setvar SomeMaxValue 55
在每个脚本的顶部,读入该公共包含文件:
:r C:\AppConfigStuff\CommonIncludeConfigVariables.sql
在每个包含的脚本中,也需要与主脚本分开运行,在变量名称的末尾使用脚本 ID 声明变量,以便它们可以单独存在或与其他脚本的变量一起存在,并使用 SQLCMD 变量作为默认值:
DECLARE @SomePath_1 NVARCHAR(500) = N'$(SomePath)', @CommonObjectA_1 NVARCHAR(128) = N'$(CommonObject)', @SomeMaxValue_1 INT = $(SomeMaxValue);
另一个脚本将具有:
DECLARE @SomePath_2 NVARCHAR(500) = N'$(SomePath)', @CommonObjectA_2 NVARCHAR(128) = N'$(CommonObject)', @SomeMaxValue_2 INT = $(SomeMaxValue);
在这两种方法中,在每个单独的脚本中使用唯一的变量名将消除任何冲突,尤其是当您有其他原因不在脚本之间放置 "GO" 语句时。
并且,在第二种方法中,如果将所有 T-SQL 变量引用替换为SQLCMD 变量引用(例如 = $(IntVar)
或 = N'$(StringVar)'
)。