Perl-скрипт, обращающийся к mysql, проверяет, существуют ли уже 3 поля вместе - PullRequest
0 голосов
/ 24 апреля 2011

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

Эта работает, но не проверяет, существует ли уже уникальная запись и добавляет без рассмотрения

#! /usr/bin/perl -w
use DBI;
use DBD::mysql;
use Data::Dumper;
# MySQL Variables

my ($username, $password, $db, $login_info);
$username=""; #omitted
$password=""; #omitted
$db=''; #omitted
$table=''; #omitted
$dbh=DBI->connect("dbi:mysql:$db", $username, $password) or die "Connection Error: $DBI::errstr\n";

    my $insert=$dbh->do("INSERT INTO $table (area, name, level, align, hp, maxhp, bash, pierce, slash, acid, air, cold, disease, earth, fire, holy, light, electric, magic, mental, negative, poison, shadow, sonic, water) VALUES ('$ARGV[0]', '$ARGV[1]', '$ARGV[2]', '$ARGV[3]', '$ARGV[4]', '$ARGV[5]', '$ARGV[6]', '$ARGV[7]', '$ARGV[8]', '$ARGV[9]', '$ARGV[10]', '$ARGV[11]', '$ARGV[12]', '$ARGV[13]', '$ARGV[14]', '$ARGV[15]', '$ARGV[16]', '$ARGV[17]', '$ARGV[18]', '$ARGV[19]', '$ARGV[20]', '$ARGV[21]', '$ARGV[22]', '$ARGV[23]', '$ARGV[24]');");

Следующей была моя попытка проверить это, но она с треском провалилась.Любая помощь будет принята с благодарностью.

#! /usr/bin/perl -w

use DBI;
#! /usr/bin/perl -w

use DBI;
use DBD::mysql;
use Data::Dumper;
# MySQL Variables

my ($username, $password, $db, $login_info);
$username=""; #omitted
$password=""; #omitted
$db=''; #omitted
$table=''; #omitted
$dbh=DBI->connect("dbi:mysql:$db", $username, $password) or die "Connection Error: $DBI::errstr\n";
my ($area, $name, $level) = ($ARGV[1], $ARGV[1], $ARGV[2]);

my $query=$dbh->prepare("SELECT name, area, level from Interrogate WHERE name=$name, area=$area, level=$level;");
$do=$query->execute(  );
if ($do) { 
    my $insert=$dbh->do("INSERT INTO $table (area, name, level, align, hp, maxhp, bash, pierce, slash, acid, air, cold, disease, earth, fire, holy, light, electric, magic, mental, negative, poison, shadow, sonic, water) VALUES ('$ARGV[0]', '$ARGV[1]', '$ARGV[2]', '$ARGV[3]', '$ARGV[4]', '$ARGV[5]', '$ARGV[6]', '$ARGV[7]', '$ARGV[8]', '$ARGV[9]', '$ARGV[10]', '$ARGV[11]', '$ARGV[12]', '$ARGV[13]', '$ARGV[14]', '$ARGV[15]', '$ARGV[16]', '$ARGV[17]', '$ARGV[18]', '$ARGV[19]', '$ARGV[20]', '$ARGV[21]', '$ARGV[22]', '$ARGV[23]', '$ARGV[24]');");
}

РЕДАКТИРОВАТЬ Удалена посторонняя фигурная скобка.

Ответы [ 2 ]

0 голосов
/ 24 апреля 2011

Вы, похоже, не понимаете, что возвращает execute из прекрасного руководства :

В случае ошибки возвращается undef. Успешное выполнение всегда возвращает true независимо от количества затронутых строк, даже если оно равно нулю (см. Ниже).
[...]
Метод execute не возвращает количество строк, которые будут возвращены запросом (поскольку большинство баз данных не могут сообщить заранее), он просто возвращает истинное значение.

Итак, вы хотите сделать что-то вроде этого:

my $query = $dbh->prepare("SELECT COUNT(*) FROM Interrogate WHERE name = ? AND area = ? AND level = ?");
$query->execute($name, $area, $level);
my $count = $query->fetchrow_arrayref();
if(!$count->[0]) {
   # do the insert
}

Я добавил заполнители (для защиты от атак SQL-инъекций) и исправил синтаксис вашего предложения WHERE бесплатно.

Еще лучше было бы поместить уникальный индекс (имя, область, уровень) внутри базы данных. Тогда вы можете просто сделать INSERT, перехватить и проигнорировать исключение «уникальное ограничение нарушено». Этот подход защищает от состояния гонки в вашем подходе: вы проверяете существующую строку, но не находите ее, другой процесс добавляет строку, вы добавляете строку, но в итоге получаете дубликат, потому что кто-то вставил его между вашей проверкой и вашим вставить. Лучше всего ставить проблемы целостности данных в базу данных, базы данных хороши в таких вещах.

0 голосов
/ 24 апреля 2011

вместо if ($do) разве вы не должны проверять возвращенное число (что-то вроде это )?И попробуйте этот оператор SQL вместо SELECT name, area, level from Interrogate WHERE name=$name AND area=$area AND level=$level; (используйте AND в предложении where)

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