我写了一个过程,它使用库DBI将数据从xml文件导入MariaDB。该过程有效,但我不明白为什么以下代码给我的信息:
use of uninitialized value $DBI::err in concatenation (.) or string at ...
这里的代码(缩写):
my $insert_art = $dbh->prepare(
"INSERT INTO odbb_articles (creation_dt,ref_data,comp_no)".
"VALUES (?,?,?)"
);
....
my $comp_no = $xpc->findvalue('./sr:ARTCOMP/sr:COMPNO',$node1);
....
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: ".
"$DBI::err -> $DBI::errstr (odbb_articles $DBI::state)\n";
如果我插入代码
if ($comp_no eq "") { $comp_no = undef; }
在 $ insert_art->执行之前,该过程有效。当元素COMPNO的xml文件中没有条目时,会发生此错误。如果我把它定义为undef,我可以避免它。我只是想知道
第二个问题的原因是如果有很多变量/列可能有空条目,则避免使用if语句。
感谢您的帮助。
答案 0 :(得分:2)
在SQL数据库中,空字符串与null非常不同。 如果comp_no有一个外键指向另一个表中的记录,那么值""只有在有""的记录时才是可加入的。作为主键,非常不可能。
Yu可以修复将空值转换为 undef :
的问题for ($creation_dt,$ref_data,$comp_no ){
defined $_ and $_ eq '' and $_ = undef;
}
$insert_art->execute($creation_dt,$ref_data,$comp_no);
或
$insert_art->execute(map {defined($_) && length($_) ? $_ : undef} ($creation_dt,$ref_data,$comp_no));
答案 1 :(得分:2)
在连接(。)或字符串中使用未初始化的值$ DBI :: err ...
您看到的错误消息是Perl告诉您$DBI::err
是undef
。这不是因为$comp_no
的价值。这只是你的计划正在做的结果。
因此,当您将空字符串传递给comp_no
列时,数据库并不喜欢这样。它抛出一个错误。 DBI捕获该错误并将其传递。 $insert_art->execute
返回false值,并调用or
的右侧。那是你的die
。
现在,在传递给die
的字符串中,您放了三个变量:
$DBI::err
$DBI::errstr
$DBI::state
根据the DBI documentation,这些功能相当于$h->err
,$h->errstr
和$h->state
,其中$h
是最后使用的句柄。让我们来看看那些文档。
从最后一个调用的驱动程序方法返回本机数据库引擎错误代码。代码通常是一个整数,但你不应该假设。
DBI在几乎所有DBI方法调用之前将$ h-> err重置为undef,因此该值仅具有较短的生命周期。此外,对于大多数驱动程序,语句句柄与父数据库句柄共享相同的错误变量,因此在一个句柄上调用方法可能会重置相关句柄上的错误。 [...]
这不能解释何时可以undef
。
从最后一个调用的DBI方法返回本机数据库引擎错误消息。这与" err"具有相同的寿命问题。上述方法。
返回的字符串可能包含由换行符分隔的多条消息。
不应该使用errstr()方法来测试错误,为此使用err(),因为驱动程序可能会返回信息'或者通过errstr()发出警告信息,告知没有失败的方法'。
好的,这是文字。不要用它来测试特定的错误。你不是那样做的。您只想在程序失败时提供调试输出。
以标准SQLSTATE五字符格式返回状态代码。请注意,特定成功代码00000将转换为任何空字符串(false)。如果驱动程序不支持SQLSTATE(并且大多数不支持),则state()将返回所有错误的S1000(常规错误)。
驱动程序可以通过状态自由返回任何值,例如警告代码,即使它没有通过" err"返回真值来声明错误。上述方法。
不应该使用state()方法来测试错误,为此使用err(),因为驱动程序可能会返回信息'或者通过state()警告状态代码,用于没有'失败的方法。
同样,这不是很清楚它的用途。
我的建议是摆脱$DBI::err
和$DBI::state
。你不需要那些来弄清问题是什么。只需输出$DBI::errstr
。
$insert_art->execute($creation_dt,$ref_data,$comp_no)
or die "Fehler bei der Ausfuehrung: " . $dbh->errstr;
现在您的程序仍然会失败,但至少您会收到一条有意义的错误消息,说明您的数据库对该语句的不满意。这比告诉您的错误处理代码中存在错误更好。
之后,其他答案可能适用于解决在第一种情况下发生这种情况的原因。
另一方面,die
上有一个单词:如果在参数末尾提供\n
,则不会打印当前脚本,行号和输入句柄行号。但那些可能对你的情况有用。你可以加入它们。
答案 2 :(得分:1)
这是一种可能的捷径:
$comp_no ||= undef;
需要注意的是,在$comp_no
评估为false的情况下,这将起作用,意味着值0实际上会导致结果也为undef,这对您来说可能或不重要。如果你的字段是数字的,我会说这很重要。