В комментарии вы говорите так:
Я выполняю этот скрипт каждые 5 минут, и это создает много одинаковых строк в таблице, я не хочу, чтобы одна и та же строка в моей таблице
Я думаю, что это именно то, что происходит.
Каждые пять минут вы запускаете свою программу.Каждый раз, когда вы запускаете программу, вы используете один и тот же файл журнала для ввода.Таким образом, одни и те же записи обрабатываются каждый раз, и новые копии данных вставляются при каждом запуске.
Нет ничего плохого в существующем коде.Он делает именно то, что вы просили.Это просто не достаточно умно.Вы должны сделать это умнее.У вас есть несколько вариантов.
- Удалить из файла журнала записи, которые были обработаны.Таким образом, вы вставляете каждую запись только один раз.
- Добавьте флаг к каждой записи в вашем файле журнала, который указывает, что она была добавлена в базу данных.Затем вы можете проверить этот флаг при обработке файла и вставлять только те записи, которые не имеют этого флага.
- Добавьте индекс в таблицу, чтобы убедиться, что он может содержать только одну копию каждой записи.Затем вам нужно будет изменить свой код, чтобы он игнорировал любые повторяющиеся ошибки данных, которые вы возвращаете из базы данных.
- Используйте
REPLACE
вместо INSERT
и убедитесь, что у вас естьисправьте первичный ключ в своей таблице, чтобы гарантировать, что дубликаты записей не будут вставлены.
Не зная журнала больше о вашем конкретном приложении, трудно понять, какой из этих вариантов является лучшим для вас.Я подозреваю, что вам будет проще всего реализовать опцию REPLACE
.
Обновление: Надеюсь, вы найдете некоторые общие комментарии к своему коду полезными.
Ваш код для открытия файла, конечно, работает, но он находится на некотором расстоянии от текущей лучшей практики.Я рекомендую а) использовать лексический дескриптор файла, б) использовать версию с тремя аргументами open()
и в) проверить возвращаемое значение из вызова.
open my $fh, '<', 'logfile'
or die "Could not open 'logfile': $!\n";
Используя переменные с именем $word1
, $word2
и т. д. это ужасная идея.Лучше было бы использовать массив:
my @words = split ' ',
Если вы действительно хотите отдельные переменные, тогда, пожалуйста, дайте им лучшие имена:
my ($day, $mon, $date, $time, $year, ... ) = split(' ');
Лично я бы включил каждую записьв хеш.
my @cols = qw[day mon date time year ... ];
# and then, in your loop
my %record;
@record{@cols} = split ' ';
Преобразование месяца в число, как вы это делаете, неуклюже.Подумайте о настройке конверсионного хэша.
my %months = (
Jan => 1,
Feb => 2,
...
);
Тогда ваш код становится (предполагая $mon
вместо $word2
):
$mon = sprintf '%02d', $months{$mon}
or die "$mon is not a valid month\n";
Но, на самом деле, вы должны использовать что-то вроде Время :: Штучка для работы с датами и временем.
my $timestamp = "$day $mon $date $time $year";
my $tp = Time::Piece->strptime($timestamp, '%a %b %d %H:%M:%S $Y');
say $tp->ymd, ' ', $tp->hms;