TRY...CATCH 似乎不起作用

TRY...CATCH doesn't seem to work

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

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. 临时table已创建
  2. 再次尝试创建
  3. 错误让我们陷入困境
  4. table 被截断,一切照常进行

会发生什么:

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

我做错了什么?

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

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

There is already an object named '#LookupLinks' in the database.

看这个例子:

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

它会产生一条错误消息:

There is already an object named '#temp' in the database.

解决方法是使用 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 服务器解析并验证了整个批次。 GO 语句会将语句放入它们自己的批次中,因此错误现在不会发生。

即使是 CeOnSql 的 也能正常工作。

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

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