SQL的try-catch语句不能处理错误(SQL Server 2008)

5

我正在尝试使用try-catch捕获SQL查询(而不是存储过程)中的错误。

出于某种原因,这个方法无法处理我的错误,我仍然会得到以下错误提示:

Msg 213, Level 16, State 1, Line 29 Column name or number of supplied values does not match table definition.

请帮忙解决一下?

begin try
create table #temp_hierarchy
    (temp_gl_number varchar(50)
    ,temp_store_location varchar(255)
    ,temp_store_key varchar(50)
    ,temp_serving_dc varchar(50)
    ,temp_exploris_db varchar(50)
    ,temp_dc_account varchar(50)
    ,temp_store_type varchar(50)
    ,temp_dvp_ops varchar(50)
    ,temp_rdo varchar(50)
    ,temp_team varchar(50)
    ,temp_dvp_sales varchar(50)
    ,temp_rds varchar(50)
    ,temp_closed varchar(50)
    ,temp_open_date varchar(50)
    ,temp_close_date varchar(50)
    ,temp_store_manager varchar(250)
    ,temp_sales_teammate varchar(250)
    ,temp_machine_shop varchar(50)
    ,temp_address varchar(250)
    ,temp_city varchar(50)
    ,temp_state varchar(50)
    ,temp_zip varchar(50)
    ,temp_phone varchar(50)
    ,temp_fax varchar(50))

insert into #temp_hierarchy
select * 
from OPENROWSET('Microsoft.ACE.OLEDB.12.0', 
    'Excel 12.0;Database=C:\SQL_DATA_REPORTING\8-31-11 Store Hierarchy.xlsx;HDR=YES', 
    'SELECT * FROM [Master List$]');

truncate table tbl_hierarchy

insert into tbl_hierarchy
select *
from #temp_hierarchy
where temp_gl_number is not null
    and temp_gl_number <> 'GLID'

select @@ROWCOUNT + ' Records sucessfully imported'

end try

begin catch
select 'ERROR: ' & ERROR_NUMBER() + '. Unable to import records, existing data was not lost.' 
end catch;
go

我猜测tbl_hierarchy和#temp_hierarchy可能有不同的列定义。 - etliens
1
你可以使用 select * INTO T from OPENROWSET... 来查看临时表所需的正确表定义。 - Martin Smith
4个回答

16

您遇到了编译时错误,这种错误无法在try-catch中捕获。

BooksOnline:

编译和语句级别重新编译错误

如果以下两种类型的错误发生在TRY...CATCH结构所在的同一执行级别中,则TRY...CATCH将无法处理:

  1. 编译错误,例如阻止批处理执行的语法错误。

  2. 在语句级别重新编译期间发生的错误,例如由于延迟名称解析而导致的编译后发生的对象名称解析错误。


2
那很有道理。我该如何捕获这个错误呢? - ChandlerPelhams
5
在那篇BOL文章的后面,它提到可以使用动态SQL或将查询包装在存储过程中。try-catch将会捕捉到它。 - etliens

1

你不应该使用 SELECT * 进行插入操作 - 永远不要这样做!这是一种不好的做法,正是导致你发布的错误。在你的选择中定义列,在查询的 INSERT 部分中也要定义列。


6
我的问题是为什么错误没有被捕获,而不是错误发生的事实。 - ChandlerPelhams
我和@ChandlerPelhams一样有同样的问题。我期望我的表定义会改变,并且当发生该情况时,我希望我的catch块能够执行。当我第一次制作存储过程时它是可以工作的。但是,一旦我的表定义的TRY Block版本被更改,由于编译错误,该存储过程甚至无法运行。 - ColinMac
永远不要说“永远不……嗯……或者永远”。我目前正在研究一种检测源表更改的方法,我们从中导入数据但无法控制。我想知道何时添加列,但我们无法在远程服务器上查询INFORMATION_SCHEMA。为了以迂回的方式检测这些更改,我正在复制我的目标表结构,然后使用“INSERT INTO DestTable SELECT * FROM SourceTable”并捕获错误,以便我可以向正确的团队发送电子邮件通知。即使是最受憎恶的语法,也总有用例......甚至是**hard gulp**可爱的GOTO关键字。xD - Nick Fotopoulos

1

HLGEM - 我经常有意使用 insert dbo.mytable select*from dbo.mySrcTbl 命令,以便捕捉模式更改,并记录、发送电子邮件。

我无法控制我所处世界中的所有表格,数据管理员在非工作时间经常处于休眠状态。


就是这个!我找到了这篇文章,就是为了这个原因。有些人只是想看世界燃烧,其中许多人显然成为了“数据沙皇”。xD - Nick Fotopoulos

0
错误是由以下语句引起的。
select @@ROWCOUNT + ' Records sucessfully imported' 

@@ROWCOUNT 是一个整数,所以首先要转换为字符串。

select convert(varchar(10),@@ROWCOUNT) + ' Records sucessfully imported' 

编辑:这是一个错误,但似乎这个错误将被catch捕获,所以你必须有另一个编译时错误导致了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接