Как я делаю несколько запросов базы данных более эффективными в Perl?

Вы пытались заменить

OdbcCommand cmd = new OdbcCommand(@"usp_BS_REPORT_LINE_LIST", _conn);

на

OdbcCommand cmd = new OdbcCommand("{call usp_BS_REPORT_LINE_LIST(?)}", _conn);
5
задан Chris 3 May 2014 в 00:15
поделиться

5 ответов

If line-count and maintainable code is your only goal, your best bet would be to use any one of the several fine ORM frameworks/libraries available. Class::DBI and DBIx::Class are two fine starting points. Just in case, you are worried about spending additional time to learn these modules - dont: It took me just one afternoon to get started and productive. Using Class::DBI for example your example is just one line:

Table->retrieve(id => $parameter)->column('UPDATE!')->update;

The only down-side (if that) of these frameworks is that very complicated SQL statements required writing custom methods learning which may take you some additional time (not too much) to get around.

6
ответ дан 18 December 2019 в 12:01
поделиться

Функция «выполнить» принимает массив, содержащий все ваши параметры.

Вам просто нужно найти способ указать, какой дескриптор оператора вы хотите выполнить, и все готово ...

Было бы гораздо лучше хранить ваши дескрипторы операторов где-нибудь, потому что, если вы каждый раз будете создавать новый и готовить его каждый раз, вы действительно не лишаетесь преимуществ "подготовки" ...

Что касается возврата всех строк, вы можете это сделать (что-то вроде "while fetchrow_hashref push") остерегайтесь больших наборов результатов, которые могут съесть всю вашу память!

2
ответ дан 18 December 2019 в 12:01
поделиться

Нет смысла проверять ошибки после каждого обращения к базе данных. Как утомительно!

Вместо этого, когда вы подключаетесь к базе данных, установите для параметра RaiseError значение true. Затем, если произойдет ошибка базы данных, будет выброшено исключение. Если вы его не поймаете (в блоке eval {}), ваша программа умрет с сообщением, аналогичным тому, что вы делали вручную выше.

4
ответ дан 18 December 2019 в 12:01
поделиться

Here's a simple approach using closures/anonymous subs stored in a hash by keyword name (compiles, but not tested otherwise), edited to include use of RaiseError:

# define cached SQL in hash, to access by keyword
#
sub genCachedSQL {
  my $dbh = shift;
  my $sqls = shift;  # hashref for keyword => sql query
  my %SQL_CACHE;
  while (my($name,$sql) = each %$sqls) {
     my $sth = $dbh->prepare($sql);
     $SQL_CACHE{$name}->{sth} = $sth;

     $SQL_CACHE{$name}->{exec} = sub {  # closure for execute(s)
        my @parameters = @_;
        $SQL_CACHE{$name}->{sth}->execute(@parameters);

        return sub {  # closure for resultset iterator  - check for undef
           my $row; eval { $row = $SQL_CACHE{$name}->{sth}->fetchrow_arrayref(); };
           return $row;
        }  # end resultset closure

     }  # end exec closure

  }  # end while each %$sqls

  return \%SQL_CACHE;

}  # end genCachedSQL


my $dbh = DBI->connect('dbi:...', { RaiseError => 1 });

# initialize cached SQL statements
#
my $sqlrun = genCachedSQL($dbh,
 {'insert_table1' => qq{ INSERT INTO database.table1 (id, column) VALUES (?,?) },
  'update_table1' => qq{ UPDATE database.table1 SET column = 'UPDATE!' WHERE id = ? },
  'select_table1' => qq{ SELECT column FROM database.table1 WHERE id = ? }});

# use cached SQL
#
my $colid1 = 1;
$sqlrun->{'insert_table1'}->{exec}->($colid1,"ORIGINAL");
$sqlrun->{'update_table1'}->{exec}->($colid1);
my $result = $sqlrun->{'select_table1'}->{exec}->($colid1);
print join("\t", @$_),"\n" while(&$result());

my $colid2 = 2;
$sqlrun->{'insert_table1'}->{exec}->($colid2,"ORIGINAL");

# ...
2
ответ дан 18 December 2019 в 12:01
поделиться

Меня очень впечатлил пример Бубакера с использованием закрытия для этого.

Точно так же, если исходной целью было сделать кодовую базу меньше и более удобной в обслуживании, я могу не избавляет от мысли, что из исходного кода требуется убрать много шума, прежде чем кто-либо приступит к преобразованию в CDBI или DBIC и т.д. (несмотря на то, что они обе прекрасные библиотеки.)

Если $ dbh был создан с RaiseError , установленным в атрибутах, большая часть этого кода исчезает:

$sql_update = qq { UPDATE database.table
                   SET column = 'UPDATE!'
                   WHERE id = ?
              };
$sth_update = $dbh->prepare($sql_update);
$sth_update->execute($parameter);

Я не вижу, что обработка ошибок в исходном коде добавляет много такого, чего вы бы не получили из ванильной матрицы , созданной RaiseError , но если это важно, взгляните на атрибут HandleError на странице руководства DBI .

Кроме того, если такие операторы не используются повторно (что часто является основной целью их подготовки, чтобы кэшировать, как они оптимизированы; другая причина заключается в смягчении последствий SQL-инъекций с помощью заполнителей), то почему бы не использовать do ?

$dbh->do($sql_update, \%attrs, @parameters);
1
ответ дан 18 December 2019 в 12:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: