我正在查看一些 T-SQL 代码(在 SQL Server 2019 环境中),其中存储过程中的参数是“重载”的 VARCHAR (15) 参数,稍后将转换为 INT。我思考这会如何出错——它实际上可能不是一个数字字符串,或者它可能代表一个太大而无法放入 INT 变量的数字。我想要一些高效的东西,我开始考虑使用 TRY_CAST 而不仅仅是 CAST,或者使用 TRY/CATCH 块,在成功时进行转换,或者在失败时允许“一条出路”。为了简化...
-- given these...
declare @AParamter varchar (15) = '214748364700'; -- 100x bigger than max INT
declare @AVariable int;
-- ...approach 1...
set @AVariable = try_cast( @AParamter as int );
if (@AVariable is null) begin
print 'ERROR: invalid parameter';
end
-- ...approach 2...
begin try
set @AVariable = cast( @AParamter as int );
end try
begin catch
print 'ERROR: invalid parameter';
end catch
两者都有效,但我想知道哪个更“高效”,即需要更少的资源(并且不可否认,与其他正在发生的事情相比,任何一个都可能是最小的),或者其中任何一个有任何隐藏的“陷阱”。
我正在使用 sys.dm_exec_*_stats 视图来收集我正在测试的存储过程的指标,并且我假设 Total_Worker_Time 和 Total_Elapsed_Time 指标是最相关的,但它们可能变化很大(在proc)很难看出哪种方法可能会产生更大(或任何)效果,无论是好是坏。所以,我问这个主要是出于好奇,想知道哪种方法是更好的做法,或者还有什么可能更好。
我尝试在网络和 StackOverflow 上搜索任何信息,但我似乎找不到任何涉及性能比较的结果。
注意:我的偏好是不要重载此参数;我个人的感觉是,它应该是多个参数,每个参数都是正确的类型,并且一次只有一个参数不为空,并进行特定检查以确保我们填写了一个且只有一个,但是......这并不是真的由我决定。
TRY_CAST
速度更快, 也更清晰。
以下脚本将向您展示:
declare @v varchar(10)='hello';
declare @i int = 1;
declare @x int;
declare @dt datetime2 = sysdatetime();
while @i < 10000
begin
set @x = try_cast(@v as int);
set @i += 1;
end;
select datediff(mcs, @dt, sysdatetime());
set @i = 1;
while @i < 10000
begin
begin try
set @x = cast(@v as int);
end try
begin catch
end catch;
set @i += 1;
end;
select datediff(mcs, @dt, sysdatetime());
如果您正在捕捉,10k 循环大约需要 1 秒,而
TRY_CAST
大约需要 30 毫秒。
原因可能很简单:
BEGIN CATCH
涉及很多带有异常处理的gubbins,例如遍历堆栈和展开。而 TRY_CAST
只能返回 null。