我遇到了try / catch错误处理的问题。 我们来看看我的(简单)代码:
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运行它,否则我会得到错误的结果。 那么如何在catch-block中捕获错误呢?
感谢您的帮助
Purclot
答案 0 :(得分:4)
您需要在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
答案 1 :(得分:1)
在一些健谈之后,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块中切换DB。但是,在解析时检查该对象存在,并尝试仅在运行时错误上捕获错误。 对象缺失错误似乎没有得到try catch块捕获的必要严重性(甚至使用完全限定名称不能工作) OP必须重新思考如何完成任务。