SQL-Server,TSQL,TRY-CATCH块

时间:2014-03-05 09:54:39

标签: sql 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

2 个答案:

答案 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必须重新思考如何完成任务。