Ошибка Perl DBI Msg: невозможно вызвать метод "selectcol_arrayref" для неопределенного значения - PullRequest
0 голосов
/ 05 марта 2010
my $dblinks = '';
$dblinks = $dbh->selectcol_arrayref("select db_link from db_links where ticket=\'LOW\'");
my $success = 0;
for my $dblink (@$dblinks) {
  $success = eval {
    my ($ret) = $dbh->selectrow_array("select 1 from "
      . $dbh->quote_identifier($dblink, 'SYSIBM', "SYSDUMMY1") );
    $ret;
  };

  if ($success) {
    &Logging (3, $I, "connect_${G_CONNECT_COUNT}", "Connect success for $dblink");
  } else {
    # Read thru the selectcol_array, check for an oracle error
    $l_msg="$dblink Result doesn't match 1";
    @l_errstr=();
    &ConnectFailed ($p_host, $p_db, $p_ars, $p_ars_sev, $l_msg, $p_cid, @l_errstr);
    # Raise a Ticket with Oracle message
    &Logging (3, $I, "connect_${G_CONNECT_COUNT}", "Connect failed for $dblink");

  }
    $l_dbh->commit();
    $l_dbh->do(qq{alter session close database link  "$dblink"});

}

Ответы [ 3 ]

5 голосов
/ 05 марта 2010

Обновление:

На самом деле вы просто присваиваете дескриптор, возвращаемый вызовом connect, $l_dbh, но вызываете метод на $dbh. Вы должны использовать строгий .

Оригинальный ответ:

Дескриптор базы данных $dbh не определен, что означает сбой соединения. Вам следует либо проверить возвращаемые значения ваших вызовов, либо указать { RaiseError => 1} в вызове connect, чтобы выяснить причину.

Кроме того, нет никаких оснований ставить префикс перед каждым вторым вызовом с помощью &: используйте ConnectFailed( ) вместо &ConnectFailed( ), если только вы не знаете, какой эффект дает префикс дополнительного вызова с помощью & и не хотите иметь этот эффект.

С perldoc perlsub :

Подпрограмма может быть вызвана с использованием явного префикса &. & является необязательным в современном Perl, как и скобки, если подпрограмма была предварительно объявлена. & не является обязательным, когда просто присваивается имя подпрограмме, например, когда она используется в качестве аргумента для defined() или undef(). Также это необязательно, когда вы хотите выполнить косвенный вызов подпрограммы с именем подпрограммы или ссылкой, используя конструкции &$subref() или &{$subref}(), хотя нотация $subref->() решает эту проблему.

... Если подпрограмма вызывается с использованием формы &, список аргументов является необязательным, и если он опущен, для подпрограммы не устанавливается массив @_: массив @_ во время вызов виден вместо подпрограммы. Это механизм повышения эффективности, которого новые пользователи, возможно, пожелают избежать. (выделение добавлено).

4 голосов
/ 05 марта 2010

Вы не показываете, где назначено $dbh. Предположительно, вы делаете это раньше. Если вы этого не сделаете, то я умоляю вас добавить эти две строчки ко всем вашим кодовым файлам:

use strict;
use warnings;

... и они спасут вас от мира боли.

Ранее, когда вы создаете дескриптор базы данных, вы должны проверить, случилось ли что-то плохое:

my $dbh = DBI->connect($data_source, $username, $password)
        or die $DBI::errstr;

Нет смысла продолжать работу с вашей программой, если вы не можете получить дескриптор db, не так ли? Если вы не умрете, вы должны по крайней мере вернуться из этой функции / метода / области кода, которая отвечает за обработку БД.

Существуют и другие проблемы с вашим кодом, такие как повсеместное использование блоков eval {} и вызов функций с &, но это было достаточно подробно рассмотрено в предыдущих вопросах на этом сайте, поэтому я рекомендую вам выполнить поиск.

0 голосов
/ 14 апреля 2010

my ($ ret) = $ dbh-> selectrow_array ( "выберите 1 из" . $ Dbh-> quote_identifier ($ dblink, 'SYSIBM' , "SYSDUMMY1" ));

Я не эксперт в DBI, но это мне немного странно.Почему одинарные кавычки вокруг SYSIBM и двойные кавычки вокруг SYSDUMMY1?Возможно, это не решит вашу проблему, но это хорошая практика.Не обязательно использовать Строгий.Это предложение.

$ dblinks = $ dbh-> selectcol_arrayref ("выберите db_link из db_links, где ticket = \ 'LOW \' ");

Вот еще одна вещь, которая выглядит действительно странно - это Слэш-побег.Я бы тоже это переписал.Может не сработать, но выглядит хорошо.

$ sql = qq { выберите db_link из db_links, где ticket = LOW};

$ dblinks =$ dbh-> selectcol_arrayref ($ sql, undef);

...