sql脚本变量默认值 [英] sql scripting variable default value

查看:26
本文介绍了sql脚本变量默认值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个脚本文件,例如测试.sql.我想从另一个脚本调用它,比如 caller.sql,在 sqlcmd 模式下使用 :r test.sql.这工作正常,但我想在 test.sql 中使用脚本变量.当我从 caller.sql 调用 test.sql 时,我可以设置脚本变量,一切都很好.但是,我想为脚本值使用默认值,这样如果调用方没有设置变量,或者如果我直接运行 test.sql(不是从 caller.sql),那么脚本变量默认为一个设置值.

I have a script file e.g. test.sql. I want to call this from another script, say caller.sql, in sqlcmd mode using :r test.sql. This works fine, but I want to use a scripting variable in test.sql. When I call test.sql from caller.sql I can set the scripting variable and all is well. However, I want to use a default value for the scripting value so that if the caller does not set the variable, or if I run test.sql directly (not from caller.sql) then the scripting variable defaults to a set value.

我尝试过诸如

begin try
 select '$(grip)'
 select 'grip value was found'
end try
begin catch
 select 'grip value was missing'
end catch

但我只收到以下消息:发生了致命的脚本错误.未定义可变抓地力.

but I just get the following message: A fatal scripting error occurred. Variable grip is not defined.

我在 test.sql 中需要什么才能应付调用者是否通过了grip"?我使用的是 MS SQL 2005

What do I need in test.sql so that it can cope with 'grip' either being passed by the caller or not? I am using MS SQL 2005

推荐答案

有一个有限的解决方法(我只在 SS2008R2 上测试过):

There is a LIMITED workaround (I've only tested it on SS2008R2):

:on error ignore -- Ensures that sqlcmd.exe will not fail when referencing an undefined scripting variable. Remove this if you want your script to work in SSMS in regular mode, too.
Declare @valueOrDefault as nvarchar(max)= N'$(value)';    
if @valueOrDefault = N'$' + N'(value)' set @valueOrDefault = N'default value'; -- Test if there is a value and, if not, assign a default; note the splitting of the reference string to avoid expansion.

-- use @valueOrDefault from now on

注意:

  • 由于 T-SQL 变量不能跨批次工作,因此您无法启动另一个批次(使用 GO),因此无法使用 :on error exit 切换到强大的错误处理.因此,您必须在脚本的其余部分进行自己的错误处理——这很重要;请参阅 SQL Server - 停止或中断 SQL 脚本的执行
  • 如果您删除 :on error ignore 以使脚本以常规模式在 SSMS 中工作,请确保在使用 sqlcmd.exe 调用该脚本时不要指定 -b 选项,因为如果引用的脚本变量不存在,这将阻止整个脚本运行.
  • 通过有效地将脚本变量转换为常规 T-SQL 变量,您不能在 T-SQL 需要文字的地方使用该值,例如 CREATE DATABASE 语句中的数据库名称.
  • 如果未定义脚本变量,则会向 stderr 打印以下警告:'variableName' 脚本变量未定义.
  • Since T-SQL variables don't work across batches, you cannot start another batch (with GO) and so cannot switch to robust error handling with :on error exit. Therefore, you have to do your own error handling in the remainder of the script - which is non-trivial; see SQL Server - stop or break execution of a SQL script
  • If you remove the :on error ignore in order to make the script work in SSMS in regular mode, be sure that when you invoke that script with sqlcmd.exe that you do NOT specify the -b option, as that will prevent the entire script from running if the referenced scripting variable does not exist.
  • By effectively turning the scripting variable into a regular T-SQL variable, you cannot use the value in places where T-SQL expects literals, such as the name of a database in a CREATE DATABASE statement.
  • If the scripting variable is not defined, the following warning is printed to stderr: 'variableName' scripting variable not defined.
-- Store the default value in the context info (session-level storage accessible across batches that holds up to 128 bytes).
declare @binDefaultValue varbinary(128)= CAST(N'default value' AS varbinary(128));
set CONTEXT_INFO @binDefaultValue;
go -- Make the set CONTEXT_INFO statement take effect.

-- If the scripting variable has a value, store ITS value in the context info instead.
:on error ignore -- Temporarily ignore errors so that accessing a non-existent scripting variable doesn't abort the entire script.
    declare @value as nvarchar(max) = N'$(value)'; -- Try to access the scripting variable; thanks to :on error ignore this will only give a warning.
    if @value <> N'$' + N'(value)' -- Test if there is a value; note the splitting of the reference string to avoid expansion.
    begin
    -- We have a scripting-variable value: Store it in the context info (replacing the default value).
        declare @binValue as varbinary(128) = cast(@value as varbinary(128));
        set CONTEXT_INFO @binValue;
    end
go -- End batch here, so we can switch back to :on error exit (requires a new batch).

:on error exit -- New batch: switch back to robust error handling.
-- End the batch here, so that SSMS in *regular* mode - which will fail on the line above - continues processing below.
-- Note that when run by sqlcmd.exe the subsequent batches will inherit :on error exit.
go

-- Retrieve the value or default value from the context info...
declare @valueOrDefault as nvarchar(max) = convert(nvarchar(max), CONTEXT_INFO(), 0);
-- ... and remove trailing null characters. ?? Is there an easier way to do this?
declare @pos as int = 0;
while @pos < LEN(@valueOrDefault)
begin
    set @pos=@pos+1
    if UNICODE(substring(@valueOrDefault, @pos, 1)) = 0  break;
end
if @pos > 0 set @valueOrDefault = left(@valueOrDefault, @pos - 1);

-- @valueOrDefault now contains the scripting-variable value or default value.
print 'Value or default value: [' + @valueOrDefault + ']';

注意:

  • 以上在从 sqlcmd.exe 和 常规 模式下的 SSMS 中调用时都有效 - 假设您在脚本中没有使用其他 SQLCMD 命令.遗憾的是,SQLCMD 模式下的 SSMS 总是拒绝运行引用不存在的脚本变量的脚本.
  • 需要使用 SET CONTEXT_INFO,因为值需要跨批处理边界传递,而 T-SQL 变量无法做到这一点.需要多批次才能切换回稳健的错误处理.
  • 上面的代码只支持单个脚本变量,并且由于使用了SET CONTEXT_INFO,其长度被限制为128字节= 64个Unicode字符;不过,也可以使用其他解决方法,例如临时表.
  • 通过有效地将脚本变量转换为常规 T-SQL 变量,您不能在 T-SQL 需要文字的地方使用该值,例如 CREATE DATABASE 语句中的数据库名称.
  • 如果未定义脚本变量,则会向 stderr 打印以下警告:'variableName' 脚本变量未定义.
  • The above works both when invoked from sqlcmd.exe and in SSMS in regular mode - assuming you use no other SQLCMD commands in the script. Sadly, SSMS in SQLCMD mode always refuses to run a script that references a non-existent scripting variable.
  • The use of SET CONTEXT_INFO is required, because values need to be passed across batch boundaries, which can't be done with T-SQL variables. Multiple batches are needed to switch back to robust error handling.
  • The code above only supports a single scripting variable, and, due to use of SET CONTEXT_INFO, its length is limited to 128 bytes = 64 Unicode characters; it's conceivable to use other workarounds, though, such as temporary tables.
  • By effectively turning the scripting variable into a regular T-SQL variable, you cannot use the value in places where T-SQL expects literals, such as the name of a database in a CREATE DATABASE statement.
  • If the scripting variable is not defined, the following warning is printed to stderr: 'variableName' scripting variable not defined.

这篇关于sql脚本变量默认值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆