Как получить несколько столбцов из запроса SQL и сохранить их в 2d массиве в perl

Предположим, у меня есть запрос вроде:

my $sql = "SELECT dev_name,
                  OID_name,
                  Obj_Val
           FROM dev_logs";

где таблица имеет такие значения, как

+----+------------+----------------------+---------+---------------------+
| id | dev_name   | OID_name             | Obj_Val | timeStamp           |
+----+------------+----------------------+---------+---------------------+
|  1 | iKazatseva | ubntWlStatRssi       | 29      | 2017-07-22 15:18:34 |
|  2 | iKazatseva | ubntWlStatSignal     | -67     | 2017-07-22 10:12:32 |
|  3 | iKazatseva | ubntWlStatCcq        | 91      | 2017-07-22 15:18:34 |
|  4 | iKazatseva | ubntWlStatNoiseFloor | -96     | 2017-07-27 16:45:24 |
+----+------------+----------------------+---------+---------------------+

Как я могу сохранить значения, возвращаемые запросом, в двумерном массиве, как показано ниже?:

+------------+----------------------+---------+
| dev_name   | OID_name             | Obj_Val |
+------------+----------------------+---------+
| iKazatseva | ubntWlStatRssi       | 29      |
| iKazatseva | ubntWlStatSignal     | -67     |
| iKazatseva | ubntWlStatCcq        | 91      |
| iKazatseva | ubntWlStatNoiseFloor | -96     |
+------------+----------------------+---------+

Я пробовал некоторые вещи, но все, что я мог получить, это связать их в 1d массив, например

my @devLogsArr = $dbh->selectall_arrayref($sql);

или же

my @OID_names= map {$_->[1]}
  @{$dbh->selectall_arrayref($sql)};

или связать их в переменных, как:

$sth->bind_col(1, \$devname);
$sth->bind_col(2, \$OID);
$sth->bind_col(3, \$value);

print "$devname\t$OID\t$value\n" while $sth->fetchrow_arrayref;

my @devLogsArr;
push(@devLogsArr, (devname=> $devname, OID=> $OID, value=> $value))
while $sth->fetchrow_arrayref;

но это далеко от того, что я хотел бы сделать. Я знаю, что это можно сделать, запросив БД для каждого отдельного столбца, но это было бы излишним.

Возможно ли то, что я здесь спрашиваю?

Заранее спасибо.

1 ответ

Решение

selectall_arrayref() возвращает ссылку на массив. Смотрите это в DBI. Таким образом, мы можем использовать его как

my $all_rows = $dbh->selectall_arrayref($sql);

присваивая его переменной, скаляру, $all_rows, Чтобы разыменовать это и создать массив

my @all_rows = @{ $all_rows };

где я использую то же имя ("all_rows") только, чтобы показать, что скаляр ($) и массив (@) с тем же именем разные переменные. Это не та практика, которую я бы порекомендовал, потому что может возникнуть путаница; тщательно выбирайте имена В этом случае { } не нужны и @$all_rows Это хорошо.

Теперь вы можете распечатать содержимое

foreach my $row (@all_rows) { 
    print "@$row\n";
}

где каждый $row извлеченный из массива сам по себе является arrayref, поэтому мы разыменовываем его (@$row), или же

print "@$_\n" for @all_rows;

Ссылки очень удобны для работы, поэтому может быть мало причин для создания фактического массива со строками; просто держи это в $all_rows, Распечатать их

print "@$_\n" for @$all_rows;

где @$all_rows разыменовывает $all_rows и создает список, который for перебирает, помещая каждый элемент в специальную переменную $_. Это тогда разыменовывается @$_ и интерполировал "@$_" в print Таким образом, мы получаем пробелы между элементами для четкого чтения.

Литература: учебник perlreftut, поваренная книга perldsc и справочник perlref.


Теперь, чтобы каким-то образом добавить к этому имена столбцов, важно сначала сформулировать цель этого. Если это для поиска, то что нужно искать чем? Если вы делаете запрос по имени столбца, то как вы хотите иметь доступ к элементам строки? По индексу или опять по имени как-нибудь? Хотите ли вы иметь возможность удобно проходить через него? Поддерживать одер столбцов?

На данный момент мы практически реализуем функциональность стиля реляционной базы данных.

Так что, возможно, просто будь проще. У arrayref есть информация, и для отображения вы можете сначала напечатать имена столбцов. О форматировании можно позаботиться через printf, подробности доступны в sprintf.

Другие вопросы по тегам