【问题标题】:TRY...CATCH doesn't seem to workTRY...CATCH 似乎不起作用
【发布时间】:2015-06-24 07:34:56
【问题描述】:

我有以下代码只是为了确保临时表不存在。如果表存在,我想截断它。

CREATE TABLE #LookupLinks(
        [SyncID] uniqueidentifier,
        [Name] nvarchar(50),
        [SQLTable] nvarchar(50)
    ) --I create this just to test my try-catch

BEGIN TRY
    CREATE TABLE #LookupLinks(
        [SyncID] uniqueidentifier,
        [Name] nvarchar(50),
        [SQLTable] nvarchar(50)
    )
END TRY
BEGIN CATCH
    PRINT N'#LookupLinks already existed and was truncated.';
    TRUNCATE TABLE #LookupLinks
END CATCH

我想要这样做:

  1. 临时表已创建
  2. 尝试重新创建它
  3. 错误让我们陷入困境
  4. 表格被截断,一切照常进行

会发生什么:

错误:数据库中已经有一个名为“#LookupLinks”的对象。

我在这里做错了什么?

【问题讨论】:

标签: sql sql-server error-handling sql-server-2012 try-catch


【解决方案1】:

这是因为 SQL Server 会解析并验证整个批次。所以在解析第二个CREATE TABLE 语句时,它会出错:

数据库中已经有一个名为“#LookupLinks”的对象。

看这个例子:

IF 1 = 1 BEGIN
    CREATE TABLE #temp(col INT)
END
ELSE BEGIN
    CREATE TABLE #temp(col INT)
END

它会产生一个错误:

数据库中已经有一个名为“#temp”的对象。

解决方法是使用Dynamic SQL

-- CREATE the table for testing
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL 
    DROP TABLE #LookupLinks 
CREATE TABLE #LookupLinks(
        [SyncID] uniqueidentifier,
        [Name] nvarchar(50),
        [SQLTable] nvarchar(50)
    ) 


-- Final query
IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL BEGIN
    TRUNCATE TABLE #LookupLinks
    PRINT N'#LookupLinks already existed and was truncated.'
END
ELSE BEGIN
    DECLARE @sql NVARCHAR(MAX) = ''
    SELECT @sql = '
        CREATE TABLE #LookupLinks(
            [SyncID] uniqueidentifier,
            [Name] nvarchar(50),
            [SQLTable] nvarchar(50)
        )'
    EXEC sp_executesql @sql
    PRINT N'#LookupLinks was created.'
END

如果您没有第一个CREATE TABLE 语句,您的查询将正常工作。或者,如果您在 BEGIN TRY 之前放置 GO

IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL 
    DROP TABLE #LookupLinks -- DROP FIRST

CREATE TABLE #LookupLinks(
        [SyncID] uniqueidentifier,
        [Name] nvarchar(50),
        [SQLTable] nvarchar(50)
    ) --I create this just to test my try-catch
GO
BEGIN TRY
    CREATE TABLE #LookupLinks(
        [SyncID] uniqueidentifier,
        [Name] nvarchar(50),
        [SQLTable] nvarchar(50)
    )
END TRY
BEGIN CATCH
    PRINT N'#LookupLinks already existed and was truncated.';
    TRUNCATE TABLE #LookupLinks
END CATCH

仍然是因为 SQL Server 解析并验证了整个批次。 GO 语句会将语句放入它们自己的批处理中,因此现在不会发生错误。

即使 CeOnSql 的 answer 也可以正常工作。

【讨论】:

    【解决方案2】:

    我认为你真正想要实现的是:

    IF OBJECT_ID('tempdb..#LookupLinks') IS NOT NULL --Table already exists
    BEGIN
        TRUNCATE TABLE #LookupLinks
        PRINT N'#LookupLinks already existed and was truncated.'; 
    END
    ELSE
    BEGIN 
        CREATE TABLE #LookupLinks(
            [SyncID] uniqueidentifier,
            [Name] nvarchar(50),
            [SQLTable] nvarchar(50)
        )
    END
    

    【讨论】:

    • 请尝试重新连接到您的服务器以获得干净的会话,它非常适合我。
    • 对我也很好。我会颠倒 PRINT 和 TRUNCATE 的顺序。由于在打印消息时查找实际上并未被截断
    • @CeOnSql 还是一样的东西.. 你使用的是 sql-server-2012 吗?
    • @wewestthemenace 当我按照您更新的解释进行操作时,它就可以工作了!感谢您和 CeOnSql =)
    • 不客气! @t-clausen.dk 谢谢你没有看 - 我改变了截断并打印到正确的顺序:)
    【解决方案3】:

    TRY CATCH 用于运行时错误。您得到的是编译时错误。在你的语句之前添加一个PRINT 1,你会看到没有任何东西被执行。

    print 1
    
        CREATE TABLE #LookupLinks(
            [SyncID] uniqueidentifier,
            [Name] nvarchar(50),
            [SQLTable] nvarchar(50)
        );
    BEGIN TRY
    
        CREATE TABLE #LookupLinks(
            [SyncID] uniqueidentifier,
            [Name] nvarchar(50),
            [SQLTable] nvarchar(50)
        );
    END TRY
    BEGIN CATCH
        PRINT N'#LookupLinks already existed and was truncated.';
        TRUNCATE TABLE #LookupLinks
    END CATCH
    

    【讨论】:

    • 刚试运行,还是报错:> 数据库中已经有一个名为“#LookupLinks”的对象。
    • 哦!谢谢。没想到我做错了^^
    • @wewestthemenace - 是的,因为我刚刚解释了它发生的原因。我没有提供任何解决方案,因为 OP 只是想看看它为什么会发生
    猜你喜欢
    • 1970-01-01
    • 2020-06-23
    • 2013-11-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多