2014-03-05 58 views
1

我遇到了try/catch错误处理问题。 让我们在我的(简单)的代码来看看:SQL-Server,TSQL,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

您是否试图使用完全限定的名称而不是更改数据库上下文,如select * from myDB2.dbo.Tab2? – jean

+0

顺便说一句,如果你想检查数据库和对象是否存在,为什么不从sys.sysdatabases和sys.sysobjects中选择? – jean

+0

嗨,让我, 正如我所说:我需要改变到数据库(所以它不是一个解决方案:select * from myDB2.dbo.Tab2 ...)。 当我使用:if(存在(从master.dbo.sysdatabase选择其中[名称] ='myDB2')1使用myDB2,我会得到一个错误 – Purclot

回答

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 
+0

谢谢,这就是我一直在寻找的答案! 谢谢,Purclot – Purclot

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真的想切换DB一个try catch块内。但是这个对象的存在是在分析时检查的,而且只有在运行时错误的情况下才会尝试工作。 另外对象缺失错误似乎没有得到必要的严重程度被try catch块捕获(甚至使用完全合格的名称生病不行)

OP必须重新考虑他如何完成任务。

+0

嗨,让, 恐怕我们只是偏离主要问题的优点: 如何获得catch-block的工作方式,当我只想切换到一个不存在的数据库时 - 出于何种原因。 HasIdentity属性的问题仅仅是一个例子。 Purclot – Purclot

+0

对不起,我的观点是避免在try catch内切换上下文。起初,我找不到有关该特定情况的任何信息。如果你真的想去,让我们多挖一点 – jean

+0

我想我发现了这个问题。当我尝试解析你的代码时会引发错误。这意味着数据库不存在不适合在解析时处理,而不是试图捕获的运行时。 – jean