如果表包含特定列,我想检查我的存储过程。如果存在这样的列,我想引发错误,因为它们是不允许的。首先,我提出了以下想法,这显然有一个我能理解的缺陷。
BEGIN TRY
SET @sql = N'SELECT TOP 0 forbidden_column_name1 INTO #t1 FROM ' + @input_table ;
EXEC @err = sp_executesql @sql ;
IF @err = 0 -- i.e. if succeeds
RAISERROR('Input table cannot contain ''forbidden_column_name1''. This name is reserved!', 16, 99) ;
SET @sql = N'SELECT TOP 0 forbidden_column_name2 INTO #t1 FROM ' + @input_table ;
EXEC @err = sp_executesql @sql ;
IF @err = 0 -- i.e. if succeeds
RAISERROR('Input table cannot contain ''forbidden_column_name2''. This name is reserved!', 16, 99) ;
SET @sql = N'SELECT TOP 0 forbidden_column_name3 INTO #t1 FROM ' + @input_table ;
EXEC @err = sp_executesql @sql ;
IF @err = 0 -- i.e. if succeeds
RAISERROR('Input table cannot contain ''forbidden_column_name3''. This name is reserved!', 16, 99) ;
END TRY
BEGIN CATCH
IF ERROR_STATE() = 99
BEGIN
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
RETURN ;
END
-- Do nothing and continue execution, if column doesn't exist
END CATCH
此代码仅检查forbidden_column_name1
的存在。不检查其他内容,因为在检查forbidden_column_name1
期间必须引发异常:来自sp_executesql
,如果列不存在,或来自RAISERROR
,如果列确实存在。无论哪种方式,执行都会传递到catch块并且永远不会返回。
我的问题是,有没有办法强制执行返回到TRY块,如果错误实际上不是错误,而是实际需要的东西。否则,我必须将所有检查放在单独的TRY / CATCH块中,这使代码看起来有点多余。
答案 0 :(得分:2)
为什么不查询sys.columns
来确定这些列的存在与否,而不是通过查询表来推断它们的存在?
e.g。
IF EXISTS(select * from sys.columns where object_id = OBJECT_ID(@table_name) and name in (
'forbidden_column1','forbidden_column2','forbidden_column3'))
BEGIN
RAISERROR('One or more forbidden columns detected. Review the documentation',16,99)
RETURN
END
--Proceed, knowing that the table doesn't contain the forbidden columns
答案 1 :(得分:1)
您必须在try / catch块中包装每个单独的select语句。
BEGIN TRY
SET @sql = N'SELECT TOP 0 forbidden_column_name1 INTO #t1 FROM ' + @input_table ;
EXEC @err = sp_executesql @sql ;
IF @err = 0 -- i.e. if succeeds
RAISERROR('Input table cannot contain ''forbidden_column_name1''. This name is reserved!', 16, 99) ;
END TRY
BEGIN CATCH
IF ERROR_STATE() = 99
EXEC usp_RethrowError
END CATCH
为避免重复自己,您可以为此创建一个过程,该过程包含表名和列名的参数。
答案 2 :(得分:0)
不是您问题的直接答案,但您最好使用INFORMATION_SCHEMA来确定列是否存在。
类似的东西:
IF EXISTS (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE
TABLE_NAME = @input_table AND COLUMN_NAME IN ('forbidden_column_name1', 'forbidden_column_name2', 'etc'))
BEGIN
RAISERROR('idiot', 16, 99)
END