Какой лучший способ прочитать строки файла и записать их в различные таблицы базы данных, используя Perl? - PullRequest
1 голос
/ 19 апреля 2020

Я пытаюсь прочитать плоский файл, который содержит номера билетов и записать данные в базу данных. Каждый билет имеет аналогичный формат, он имеет записи в строках (R) и столбцах (C) разной длины (обозначается числом в скобках). База данных содержит 3 таблицы с именами R1_table, R2_table и R3_table для хранения строк из плоского файла. Все записи в строках 1, 2 и 3 заявки начинаются с 10, 20 и 30 соответственно, и это то, что я использую, чтобы определить, в какой таблице базы данных данные строки должны go. Плоский файл выглядит так;

# Ticket_0001 
10 Field_R1_C1(40) Field_R1_C2(32) Field_R1_C3(8) ... Field_R1_Cn(3)
20 Field_R2_C1(20) Field_R2_C2(12) Field_R2_C3(18) ... Field_R2_Cn(6)
30 Field_R3_C1(30) Field_R3_C2(10) Field_R3_C3(2) ... Field_R3_Cn(12)
...

# Ticket_000n
10 Field_R1_C1(40) Field_R1_C2(32) Field_R1_C3(8) ... Field_R1_Cn(3)
20 Field_R2_C1(20) Field_R2_C2(12) Field_R2_C3(18) ... Field_R2_Cn(6)
30 Field_R3_C1(30) Field_R3_C2(10) Field_R3_C3(2) ... Field_R3_Cn(12)

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

my $R1_table = "R1_table"; # table name for row 1 records
my @R1_columns = qw(Field_R1_C1 Field_R1_C2 Field_R1_C3 ... Field_R1_Cn); # column names for R1_table
my @R1_column_start = (1, 41, 73, ...250); # starting positions for columns in R1_table
my @R1_column_end = (40, 72, 80 ... 300); #ending positions for columns R1_table
...
# same for the next tables R2_table and R3_table

my $filename = 'ticket.dat';
open(my $fh, '<:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";

while (my $row = <$fh>) {
  write_to_db($row); # call subroutine and write record to database
}


sub write_to_db 
{
    my $row = shift;
    my $record_type = substr($row, 0, 2); # to identify which table to write to
    my $record; 
    my $column_size;
    my @insert_data;
    my $offset = 0;

    if($record_type eq '10'){
        for(my $i = 0; $i <= $#R1_column_end; $i++){
            # break row data into columns
            $offset = $R1_column_start[$i] - 1;
            $column_size = $R1_column_end[$i] - $R1_column_start[$i] + 1;
            $record = substr($row, $offset, $column_size); 
            push @insert_data, $record; # add column to an array
        }
        my $sql_fields = join(",", @R1_columns);
        my $sql_placeholders = join(",", map {"?"} @R1_columns);

        # prepare your statement for connecting to the database
        $dbh->prepare("INSERT INTO $R1_table ($sql_fields) VALUES ($sql_placeholders)")->execute(@insert_data);
    }
    if($record_type eq '20'){#same body as above but with R2_table and columns instead }
    if($record_type eq '30'){#same body as above but with R3_table and columns instead }
}

Я надеюсь, вы понимаете, что я пытаюсь сказать. Мой вопрос: как лучше всего прочитать строки файла и записать их в различные таблицы в базе данных?

1 Ответ

3 голосов
/ 19 апреля 2020

Вместо разных переменных для разных таблиц используйте ha sh для хранения всей информации:

my %tables = (
    R1 => [ [ 'Field_R1_C1', 11, 40 ],
            [ 'Field_R1_C2', 41, 72 ],
            [ 'Field_R1_C3', 73, 80 ],
            ...,
            [ 'Field_R1_Cn', 250, 300 ] ],
    R2 => [ [ ... ] ],
);

Затем измените пишущий саб, чтобы использовать эту структуру:

sub write_to_db {
    my ($row) = @_;

    my $record_type = substr $row, 0, 2;
    my %table_names = ( 10 => 'R1',
                        20 => 'R2',
                        30 => 'R3' );
    my $table = $table_names{$record_type};
    die "Unknown table for record type $record_type\n"
        unless defined $table;

    my @insert_data;
    for my $column (@{ $tables{$table} }) {
        my ($column_name, $column_start, $column_end) = @$column;
        my $record = substr $row, $column_start - 1,
                            $column_end - $column_start + 1;
        push @insert_data, $record;
    }
    my $sql_columns = join ',', map $_->[0], @{ $tables{$table} };
    my $placeholders = join ',', ('?') x @insert_data;
    my $insert = $dbh->prepare(
        "INSERT INTO $table ($sql_columns) VALUES ($placeholders)");
    $insert->execute(@insert_data);
}

И назовите это для каждой строки:

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