DBI:在 eval 中引发错误

2024-05-02

这个问题参考了池上的评论:

[...] But if you're going to put an eval around every statement, just use RaiseError => 0. [...]

in this thread https://stackoverflow.com/questions/12635495/should-i-put-the-eval-in-the-subroutine-or-the-subroutine-in-the-eval.

如果我设置,我会得到什么RaiseError to 0在这种情况下?

#!/usr/bin/env perl
use warnings;
use 5.10.1;
use DBI;

my $db = 'my_test_sqlite_db.sqlite';
open my $fh, '>', $db or die $!;
close $fh or die $!;

my ( $dbh, $sth );
eval {
    $dbh = DBI->connect( "DBI:SQLite:dbname=$db", "", "", {} );
};
if ( $@ ) { print $@ };

my $table = 'my_sqlite_table';

say   "RaiseError = 1";
say   "PrintError = 0";
$dbh->{RaiseError} = 1;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 1";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 1;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

say "\nRaiseError = 0";
say   "PrintError = 0";
$dbh->{RaiseError} = 0;
$dbh->{PrintError} = 0;
eval {
    $sth = $dbh->prepare( "SELECT * FROM $table" );
    $sth->execute();
};
if ( $@ ) { print "ERROR: $@" };

Output:

RaiseError = 1
PrintError = 0
ERROR: DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 23.

RaiseError = 0
PrintError = 1
DBD::SQLite::db prepare failed: no such table: my_sqlite_table at ./perl2.pl line 33.
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 34.

RaiseError = 0
PrintError = 0
ERROR: Can't call method "execute" on an undefined value at ./perl2.pl line 44.

如果由于某些原因失败,大多数 $dbh 方法将:

  • (if RaiseError选项设置为 0) 返回undef
  • (if RaiseError选项设置为 1) 立即退出脚本 ('die'),并以退出消息形式给出错误原因。

这里的关键点是,如何处理错误取决于您。例如,如果您愿意,您可以忽略它们(以下显然适用于RaiseError set to 0 only):

for my $db ( ... ) {
    my $dbh = get_database_handle( $db )
       or next;
    ...
}

在此片段中(从您在问题中提到的@ikegami的答案复制),您循环遍历数据库连接的一些设置列表;如果某些连接给你一个undef,你只需去寻找另一个,并且不做任何错误。

不过,通常情况下,当错误发生时,你要做的不仅仅是“下一步”——但话又说回来,你有两个选择:要么检查each $dbh- 相关声明如下:

$sth = $dbh->prepare('some_params') 
  or process_db_error('In prepare');
...
$res = $sth->execute('another_set_of_params') 
  or process_db_error('In execute');
...
$res->doAnythingElse('something completely different') 
  or process_db_error('In something completely different');

(as or仅当其相应的“左侧部分”评估为时才会执行部分false在布尔上下文中).

...或者只是将所有这些包装到 Perlish 的“try-catch”块中:

if (!eval {    
   $sth = $dbh->prepare('some_params');
   ...
   $res = $sth->execute('another_set_of_params');
   ...
   $res->doSomethingElse('something completely different') 
   ...
   1  # No exception
}) {
   process_db_error($@);
}

选择什么,由您决定:这是“返回语句中的错误”(除了要获取实际错误,您必须询问 $dbh 对象)和异常之间的常见决定。

但底线是你不能只写这样的:

$sth = $dbh->do_something('that_can_result_in_error');
$sth->do_something('else');

...如果你确实设置了RaiseError to 0。在这种情况下脚本不会死,$sth将被分配一个undef,并且您会遇到“派生”错误(因为您无法调用方法undef).

这正是您原来问题的代码最后部分所发生的情况。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DBI:在 eval 中引发错误 的相关文章

随机推荐

  • 如何按布尔值对数组进行排序

    我有一个看起来像这样的数组 array array foo gt true array foo gt false array foo gt true array foo gt true array foo gt false 有没有一种简单的
  • 如何在 mongodb + C# 中计数、选择和更新嵌套元素

    我正在创建一个开源社交网络 我不知道是否可以在此处发布 URL 使用 net core 2 1 mongo atlas 使用驱动程序 v2 9 2 我正在从 MS SQL 我知道如何对其进行操作 迁移到 mongo 我仍在学习 我有两个实体
  • IE 11 使用 HTML input=file 标签时锁定文件

    我在 IE11 中使用文件输入中的浏览来选择文件 我在资源管理器中使用shift delete删除了该文件 然后 当我刷新文件夹时 我删除的文件会再次出现在资源管理器中 无论如何 我可以通过客户端 JavaScript 释放文件句柄吗 我在
  • 在 Haskell/Yampa 和 HOOD 中调试游戏对象的输出

    我一直坚持使用 Haskell Yampa Arrows with HOOD 为我的游戏对象生成调试输出 我的引擎基本上运行一系列游戏对象 这些对象产生输出状态 线 圆 然后进行渲染 data Output Circle Position2
  • 动态添加导航抽屉中的项目

    我创建了抽屉 但是我想动态设置抽屉的项目列表 意味着从数据库获取数据并设置为抽屉列表 是否可以 是的 比如何 我也知道静态抽屉 尝试这个 final Menu menu navigationView getMenu for int i 1
  • .Net HashSet唯一性计算完全基于哈希码吗?

    我想知道 Net 是否HashSet
  • xmlstarlet:通过位置号选择元素

    我有这个 XML 文件
  • 如何在
    CSS 中正确定位箭头

    我想更改详细信息中出现的箭头的位置 我尝试过 float left 但如果线条太大 如上面示例中的线条 则当我调整窗口大小时 箭头将移动到下方线条的开头 我希望它保留在第一行的第一个字母之外 我怎样才能做到这一点 Example
  • WebAPI如何处理嵌套资源?

    我正在寻找有关使用 WebAPI 2 时最佳实践的意见和建议 假设我有两个控制器 用户和书籍 并且想要接受这些路由 users user id books lt books owned by user id books lt all boo
  • 在 Windows 上使用 Python 打开设备句柄

    我正在尝试使用 Giveio sys 驱动程序 该驱动程序需要先打开一个 文件 然后才能访问受保护的内存 我正在查看 WinAVR AVRdude 中的 C 示例 它使用以下语法 define DRIVERNAME giveio HANDL
  • Java-Android 上的 MulticastSocket 问题

    我开始使用 MulticastSocket 进行编码 尝试制作一个带有客户端和服务器的简单应用程序来发送消息 我的服务器代码 import java io IOException import java net DatagramPacket
  • 具有多个 FROM 表的 TableGateway

    我想做一个简单的INNER JOINZend2 中的两个表之间 具体来说 我想在 Zend2 中这样做 SELECT FROM foo bar WHERE foo foreign id bar id 我有一个FooTable class F
  • 尝试使用 C#.Net 编码 HMAC-SHA256

    我尝试将 HMAC SHA256 算法编码为函数 HMAC K m H K opad H K ipad m where H 是加密哈希函数 K 是一个秘密密钥 在哈希函数的输入块大小或原始密钥的哈希值 如果它长于该块大小 的右侧添加了额外的
  • font-face 声明中还需要 eot、ttf 和 svg 吗?

    到目前为止 我一直使用 Paul Irish 的防弹字体语法 http www paulirish com 2009 bulletproof font face implementation syntax 但我只是在寻找对 woff 和 w
  • 将表中的行相对于另一个表拖放[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 嘿 我有两个行数相同的表 例如 如果我尝试对 tableOne 中的一行 例如 row 3 进行排序 则其他表 tabl
  • printf 字符串,可变长度项

    define SIZE 9 int number 5 char letters SIZE this wont be null terminated char fmt string 20 sprintf fmt string d ds SIZ
  • scala-js 如何与 sbt-web 集成?

    我想用scala js https github com scala js scala js with sbt web https github com sbt sbt web以这样的方式 它可以被编译以生成添加到资产管道中的 JavaSc
  • 如何用 PHP 编写固定宽度的文本文件

    我正在尝试做一些应该很容易的事情 但遇到了问题 我想要做的就是从 MySQL 表生成报告 并将其作为纯 txt 文件 我需要文件固定宽度 因此一切都排列整齐并且看起来不错 我将使用 courier 字体 它只是一个准系统表格 但我如何才能真
  • 当应用程序崩溃时,Android Studio ADB 会清除 logcat 文件!哦美伊

    刚刚升级了最新的Android Studio 现在 当应用程序崩溃时 日志文件 adb logcat 就会消失 它不仅停止记录整个日志似乎突然被删除了 对于调试来说不太酷 我需要设置日志缓存大小或其他什么吗 还注意到调试器需要很长时间来收集
  • DBI:在 eval 中引发错误

    这个问题参考了池上的评论 But if you re going to put an eval around every statement just use RaiseError gt 0 in this thread https sta