Построение запроса из модуля - лучшие практики - PullRequest
0 голосов
/ 03 июня 2018

У меня есть несколько запросов, которые могут содержать до 100 или даже больше строк, которые необходимо выполнить, и я ищу лучшие практики / простой способ импортировать запросы из модуля в мой основной файл, связывать значения и выполнять их.Пример:

Sql.pm

package Sql;

use strict;
use warnings;

use Exporter;

our @ISA = qw(Exporter);
our @EXPORT_OK = qw($query);

our $query = "SELECT * 
FROM ?
";

Main.pl

use strict;
use warnings;

use Sql;
#use DBI & connect ;

my $select = $Sql::query;
my $tbl= 'my_tbl';

my $sth = $dbh->prepare($select );
$sth->execute($tbl);

Это даст мне эту ошибку:

ct_result (ct_dynamic (CS_PREPARE)) вернул -205 в строке /usr/lib/x86_64-linux-gnu/perl5/5.22/DBD/Sybase.pm 138.
DBD :: Sybase :: db Подготовка не удалась: номер сообщения сервера = 1087 серьезность = 16состояние = 1 строка = 1 сервер = локальный текст = необходимо объявить переменную таблицы "@ P1".Номер сообщения сервера = 8180 серьезность = 16 состояние = 1 строка = 1 сервер = localtext = Оператор (ы) не может быть подготовлен.в строке main.pl 16. Не могу вызвать метод "execute" для неопределенного значения в строке main.pl 17.

Если я сделаю это в моем файле main.pl

my $sth = $dbh->prepare($select);
$sth->bind_param(1, $tbl);
$sth->execute(1);

Я получаю ту же ошибку, но говорю мне, что «Не могу вызвать метод« bind_param »для неопределенного значения»

Что я делаю не так?Есть ли лучший / простой / лучший способ достижения того, что я пытаюсь сделать?

Спасибо

1 Ответ

0 голосов
/ 03 июня 2018

Я надеюсь, что приведенное ниже достаточно самоочевидно:

package My_App::Table_Name;

use feature 'state';
# save performance hit on `prepare` statements
# you said SQL statements of 100+ lines

sub sql_name {
    my $class = shift;
    my $dbh   = shift;
    my %params = @_;

    # do some checking on the params if needed, or use Type::Params::compile

    state $sth = $dbh->prepare( <<    END_OF_SQL ); # 4 spaces for neatness

        SELECT * FROM table_name WHERE col_foo = ? AND col_bar = ?

    END_OF_SQL

    $sth->execute(
        $params{foo},
        $params{bar},
    );
    return $sth->fetchall_hashref('id'); # or what ever
}

1;

А затем в вашем приложении:

use strict;
use warnings;

use DBI;
use My_App::Table_Name;

my $dbh = ... ; # RaiseError is your friend

my $results = My_App::Table_Name->sql_name($dbh,
    foo => 'abc',
    bar => '123',
);

# $results now contains a HashRef where the keys are the id's from the returned
# rows, each row being a HashRef itself, so you can do things like:

say $results->{42}->{col_foo};

Таким образом, вы можете организовать свои операторы SQL по имени таблицы, чаще всегоИзменения базы данных выполняются для одной таблицы или из-за изменений внутри одной таблицы, что приводит к цепочке отключений обновлений в других местах.

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

sub create { ... };
sub delete { ... };
sub search_joined_with_table_other { ... };

и, следовательно, в вашем приложении:

My_App::Table_Name->create($dbh,
    foo => 'xyz',
    bar => '345',
);

My_App::Table_Other->delete($dbh, id => 42 );

Итак, в принципе, вы НЕ заботитесь обо всех этих SQL-кодах внутри вашего основного приложения, а просто удалили их внутри своих собственных пакетов.А внутри вашего приложения вам даже не нужно знать, что под капотом находится SQL, вы просто вызываете методы класса.

На следующем уровне будет возвращаться объект Row для каждого пакета Table_Name и иметь свои собственные методы экземпляра.на нем.

Удачного кодирования и запоминания TIMTOWTDI (есть несколько способов сделать это)

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