【问题标题】:How to store the runtime mssql error in a variable and continue to run in perl?如何将运行时 mssql 错误存储在变量中并继续在 perl 中运行?
【发布时间】:2017-05-16 08:58:40
【问题描述】:

我正在尝试将运行时 mssql 错误存储在变量中并继续处理所有其他数据。

my $sth = $dbh->prepare("exec TEST_ABC_DB.dbo.testprocedure");
$sth->execute() ;
my $db_error =$DBI::errstr; #It didn't work also I tried err and state
print "\nDB error $db_error\n";
while (@row = $sth->fetchrow_array( ) ) 
{
      print "Row: @row\n";
}

我使用了 eval 块,但它也不起作用。

我的程序如下,(示例)

CREATE procedure  testprocedure as
select 'one'
select 'three'
select 10/0
select 'five'

当我运行脚本时它显示

输出是

Row: one
DBD::ODBC::st finish failed: [unixODBC][FreeTDS][SQL Server]Divide by zero error encountered. (SQL-22012) at testing.pl line 24.
DBI::db=HASH(0xbe79a0)->disconnect invalidates 1 active statement handle (either destroy statement handles or call finish on them before disconnecting) at testing.pl line 28.

即使three 也不显示输出。显示唯一的一个。

【问题讨论】:

  • 如果您想在过程本身中执行此操作,您可以使用 Try..Catch 块进行异常处理。请参阅此处的文档https://msdn.microsoft.com/en-us/library/ms175976.aspx
  • 您想继续执行脚本并仅捕获错误吗?
  • @AbhiNickz 是的,我想继续脚本。
  • @AbhiNickz 我试过了,但没用。报同样的错误。

标签: sql-server perl dbi


【解决方案1】:

PrintError 句柄属性告诉 DBI 调用 Perl warn() 函数(这通常会导致错误被打印到 遇到时出现屏幕)和 RaiseError 句柄属性(其中 告诉 DBI 在出错时调用 Perl die() 函数,通常是 导致脚本立即中止)。 - Programming the Perl DBI

因此,您可以使用以下来处理这种情况。

local $SIG{__DIE__} = sub {
    my ($die_message) = @_;
    #do something..
};

我正在尝试将错误存储在变量中

上面的 sn -p $die_message 会包含错误信息。


另一种选择是将RaiseError 设置为0 并将PrintError 设置为1,这样您就可以得到warnings 但程序不会die

打印错误

PrintError 属性可用于强制生成错误 除了在 正常的方式。当设置为“on”时,任何导致错误的方法 发生将导致 DBI 有效地执行warn("$class $method failed: $DBI::errstr") 其中$class 是驱动程序类和 $method 是失败的方法的名称。

引发错误

RaiseError 属性可用于强制引发错误 异常,而不是简单地以正常方式返回错误代码。它 默认为“关闭”。当设置为“on”时,任何会导致 错误将导致 DBI 有效地执行die("$class $method failed: $DBI::errstr"),其中$class 是驱动程序类,并且 $method 是失败的方法的名称。

来源 - DBI docs


你也可以手动完成

my $dbh=DBI->connect(....{RaiseError=>1}) or die...
my $sth=$dbh->prepare(...);
{
   local $dbh->{RaiseError} = 0;
   $sth->execute;
   if ($sth->Errstr) {
       # handle the error
   }
}
# $dbh->{RaiseError} is back to normal here

【讨论】:

  • 为什么不直接从RaiseError切换到PrintError
  • @Chankeypathak 如何防止dbi abort
  • @mkHun 正如 dgw 所说,关闭 RaiseError 并启用 PrintError 将阻止中止。
  • @ChankeyPathak 我通过this 问题得到了我的问题的答案。我也用了你的把戏。感谢您的帮助。
【解决方案2】:

我从this 答案中得到了我的问题的答案。

最后的答案是

do
{ 
while(my @row=$sth->fetchrow_array())
{
    if ($sth->errstr) 
    {
        my $Error = $sth->errstr;   

    }
    print $row[0]."\n\n";
}
} while ($sth->{odbc_more_results});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-12
    • 2014-08-29
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多