我在尝试/捕获错误处理方面遇到问题。让我们来看看我的(简单)代码:
BEGIN TRY
print 'important'
use myDB1; -- no problem, the myDB1 is in place...
select * from dbo.Tab1;
use myDB2;
--here error, the myDB2 is not there,
--but error handling doesn't jump into catch-block
select * from dbo.Tab2;
END TRY
BEGIN CATCH
print 'myDB2 is not there'
END CATCH
我知道,我可以说:
select * from myDB2.dbo.Tab2
而不更改为 myDB2,但是当我需要检查(例如..)表是否具有标识时
(((SELECT OBJECTPROPERTY( OBJECT_ID('myDB2.dbo.'+ @TableName), 'TableHasIdentity'))= 1)
我必须从 myDB2 运行它,否则我会得到错误的结果。那么我怎样才能在捕获块中捕获错误呢?
感谢您的帮助
普克洛特
测试条件封装在 EXEC 中,以便将错误视为运行时问题。然后,您需要为命中可能不存在的数据库的查询完全限定对象,以便可以避免使用 USE 语句。对于需要本地上下文的函数(如 OBJECTPROPERTY),可以使用 sp_executesql 在不同的数据库上下文中运行查询并返回可用结果。
DECLARE @TableName SYSNAME,
@SQL NVARCHAR(MAX),
@Result BIT
BEGIN TRY
USE [master];
SELECT TOP 1 * FROM sys.objects
SET @TableName = N'sysjobhistory'
SET @Result = 0
SET @SQL = N'USE [msdb]; DECLARE @Result BIT;
SET @TempResult = OBJECTPROPERTY( OBJECT_ID(N''' + @TableName +
N'''), ''TableHasIdentity'')'
EXEC sp_executesql @SQL,
N'@TempResult BIT OUTPUT',
@TempResult = @Result OUTPUT
SELECT @Result AS [ResultThatCanBeUsedLocally]
EXEC('USE [NotHere];')
SELECT TOP 1 * FROM NotHere.sys.objects
END TRY
BEGIN CATCH
PRINT 'Error!!'
PRINT ERROR_MESSAGE()
END CATCH
经过一些闲聊的评论,OP 只需要知道表是否有身份。您可以使用它来列出给定数据库中没有标识的表
SELECT TABLE_NAME
FROM MyDB2.INFORMATION_SCHEMA.TABLES
WHERE Table_NAME NOT IN (
SELECT c.TABLE_NAME
FROM MyDB2.INFORMATION_SCHEMA.COLUMNS c
INNER JOIN MyDB2.sys.identity_columns ic ON c.COLUMN_NAME = ic.NAME
)
AND TABLE_TYPE = 'BASE TABLE'
编辑
经过更多的聊天和挖掘,我发现 OP 真的想在 try catch 块内切换数据库。但是该对象是否存在是在解析时检查的,并且尝试捕获仅在运行时错误时才起作用。此外,对象缺失错误似乎无法获得必要的严重性来被 try catch 块捕获(即使使用完整的限定名也不起作用)
OP必须重新考虑如何完成任务。