2014-01-10 3 views
2

Я пытаюсь вставить запись в базу данных MySQL с использованием Perl DBI. Я не получаю никаких ошибок, но вставка не работает. Однако я могу успешно извлекать записи из базы данных с помощью DBI.Невозможно вставить запись в базу данных MySQL с помощью DBI

Вот код, который делает вставки:

#!"C:\xampp\perl\bin\perl.exe" 

use diagnostics; 
use DBI; 
use strict; 
use warnings; 

my $driver = "mysql"; 
my $database = "mysql"; 
my $dsn = "DBI:$driver:database=$database"; 
my $userid = "root"; 
my $password = "password"; 

my $buffer; 
my @pairs; 
my $pair; 
my $name; 
my $value; 
my %FORM; 

# Read in text 
my $ENV; 
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/; 
if ($ENV{'REQUEST_METHOD'} eq "GET") 
{ 
    $buffer = $ENV{'QUERY_STRING'}; 
} 

# Split information into name/value pairs 
@pairs = split(/&/, $buffer); 
foreach $pair (@pairs) 
{ 
    ($name, $value) = split(/=/, $pair); 
    $value =~ tr/+/ /; 
    $value =~ s/%(..)/pack("C", hex($1))/eg; 
    $FORM{$name} = $value; 
} 

my $first_name= $FORM{name}; 
my $address = $FORM{address}; 
my $city = $FORM{city}; 
my $occupation = $FORM{occupation}; 
my $age = $FORM{age}; 

my $dbh = DBI->connect("dbi:mysql:dbname=mysql", "root", "password",{ AutoCommit => 0,RaiseError => 1},) or die ("Couldn't connect to database: ") , $DBI::errstr; 

# my $sth = $dbh->prepare("INSERT INTO persons 
         # (FirstName, LastName,Address,City) 
         # values 
         # ($first_name, $last_name,$address,$city)"); 
my $query = "insert into userrecords(Address,Age,City,Name,Occupation) 
      values (?, ?, ?, ?, ?) "; 

my $statement = $dbh->prepare($query) or die ("Couldn't connect to database: "), $DBI::errstr; 
$statement->execute($address,$age,$city,$name,$occupation) or die ("Couldn't connect to database: "), $DBI::errstr; 

$dbh->disconnect(); 

my $URL = "http://.....:81/cgi-bin/showdata.cgi"; 
print "Location: $URL\n\n"; 

exit(0); 

Когда я запускаю мой код в Падре IDE, я получаю следующие ошибки:

****Error********* 
Useless use of a variable in void context at InsertRecord.cgi line 50 (#1) 
    (W void) You did something without a side effect in a context that does 
    nothing with the return value, such as a statement that doesn't return a 
    value from a block, or the left side of a scalar comma operator. Very 
    often this points not to stupidity on your part, but a failure of Perl 
    to parse your program the way you thought it would. For example, you'd 
    get this if you mixed up your C precedence with Python precedence and 
    said 

     $one, $two = 1, 2; 

    when you meant to say 

     ($one, $two) = (1, 2); 

    Another common error is to use ordinary parentheses to construct a list 
    reference when you should be using square or curly brackets, for 
    example, if you say 

     $array = (1,2); 

    when you should have said 

     $array = [1,2]; 

    The square brackets explicitly turn a list value into a scalar value, 
    while parentheses do not. So when a parenthesized list is evaluated in 
    a scalar context, the comma is treated like C's comma operator, which 
    throws away the left argument, which is not what you want. See 
    perlref for more on this. 

    This warning will not be issued for numerical constants equal to 0 or 1 
    since they are often used in statements like 

     1 while sub_with_side_effects(); 

    String constants that would normally evaluate to 0 or 1 are warned 
    about. 

Useless use of a variable in void context at InsertRecord.cgi line 59 (#1) 
Useless use of a variable in void context at InsertRecord.cgi line 60 (#1) 

Use of uninitialized value in transliteration (tr///) at InsertRecord.cgi line 
     23 (#2) 
    (W uninitialized) An undefined value was used as if it were already 
    defined. It was interpreted as a "" or a 0, but maybe it was a mistake. 
    To suppress this warning assign a defined value to your variables. 

    To help you figure out what was undefined, perl will try to tell you the 
    name of the variable (if any) that was undefined. In some cases it cannot 
    do this, so it also tells you what operation you used the undefined value 
    in. Note, however, that perl optimizes your program and the operation 
    displayed in the warning may not necessarily appear literally in your 
    program. For example, "that $foo" is usually optimized into "that " 
    . $foo, and the warning will refer to the concatenation (.) operator, 
    even though there is no . in your program. 

Use of uninitialized value $ENV{"REQUEST_METHOD"} in string eq at 
     InsertRecord.cgi line 24 (#2) 
Use of uninitialized value $buffer in split at InsertRecord.cgi line 29 (#2) 
Location: http://.......:81/cgi-bin/showdata.cgi 

Press any key to continue . . . 

***********END*********************** 

Что такое проблема?

+0

Должна быть ошибка при сбое вставки. –

+0

Проверьте дополнительную ошибку !!! – user3181823

+0

Считаете ли вы, что 'my $ ENV' и' $ ENV {'REQUEST_METHOD'} 'относятся к одной и той же переменной? Потому что это не '% ENV' - это предопределенный хэш, содержащий переменные среды. – TLP

ответ

1

Что происходит, когда вы замените код следующим образом:

#!"C:\xampp\perl\bin\perl.exe" 
use strict; 
use warnings; 

use diagnostics; 
use DBI; 
use CGI qw[param redirect];  

my $driver = "mysql"; 
my $database = "mysql"; 
my $dsn  = "DBI:$driver:database=$database"; 
my $userid = "root"; 
my $password = "password"; 

my $dbh = DBI->connect("dbi:mysql:dbname=mysql", "root", "password", 
    { AutoCommit => 0,RaiseError => 1},) 
    or die "Couldn't connect to database: ", $DBI::errstr; 

my $query = "insert into userrecords(Address,Age,City,Name,Occupation) 
values (?, ?, ?, ?, ?) "; 

my $statement = $dbh->prepare($query) 
    or die "Couldn't connect to database: " , $DBI::errstr; 
$statement->execute(param('address'), param('age'), param('city'), 
        param('name'), param('occupation')) 
    or die "Couldn't connect to database: " , $DBI::errstr;  
$dbh->disconnect(); 

my $URL = "http://.....:81/cgi-bin/showdata.cgi"; 
print redirect($URL); 

Я в основном сделал два изменения:

  1. Используйте модуль CGI.pm для обработки взаимодействия CGI (получение параметров и печать заголовка перенаправления).
  2. Исправлены ошибки «пустотного контекста», удаляя беспорядочные круглые скобки во всех ваших вызовах до die.

Я не внес существенных изменений в код, но, по крайней мере, у нас теперь есть чистая версия.

Обновление: D'oh. Очевидно, теперь код немного очищается. Если вы отключили «Автокоммит», вам необходимо внести изменения.Добавить $dbh->commit между звонками до execute() и disconnect().

2

Когда я редактировал свой код так, чтобы он был более читабельным, я наткнулся на то, что я принимаю решение:

Вы используете $name при вставке в базу данных, но вы используете $first_name при получении значения $FORM{name} , Так как вы использовали $name выше, он имеет значение используемого имени, что бы это ни было. Соответствующие фрагменты кода:

($name, $value) = split(/=/, $pair); 
... 
$FORM{$name} = $value; 
... 
my $first_name = $FORM{name}; 
... 
$statement->execute($address,$age,$city,$name,$occupation) 
#          ^^^^^--- should be $first_name 

Ваша проблема была бы решена, если бы вы использовали правильную сферу ваших переменных, а именно что-то вроде этого:

foreach my $pair (@pairs) { 
    my ($name, $value) = split(/=/, $pair); 
    $value =~ tr/+/ /; 
    $value =~ s/%(..)/pack("C", hex($1))/eg; 
    $FORM{$name} = $value; 
} 

Затем, когда вы позже будет пытаться использовать $name, вы получите сообщение об ошибке

Global variable "$name" requires explicit package name ... 

, который предупредит вас о вашей ошибке и сэкономит вам время на отладку. Когда вы объявляете переменные в верхней части сценария, а не в наименьшей возможной области, вы эффективно отключите защиту, которую предлагает use strict 'vars'. Так что не делай этого.

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

Ваш скрипт при очистке и правильно отформатированные выглядит как this.

1

Предупреждение приходит от этого:

or die ("Couldn't connect to database: ") , $DBI::errstr; 

, $DBI::errstr находится вне фильеры, и ничего не делать с ним, таким образом, находясь в пустом контексте. Вы хотите что-то вроде этого:

or die ("Couldn't connect to database: $DBI::errstr"); 

Кроме того, у вашего кода обработки формы есть некоторые проблемы. Если вы пишете сценарии CGI, вы также можете использовать модуль CGI. Вот быстрый зачистка код:

#!"C:\xampp\perl\bin\perl.exe" 
use diagnostics; 
use CGI ':standard'; 
use DBI; 
use strict; 
use warnings; 

my $driver = "mysql"; 
my $database = "mysql"; 
my $dsn  = "DBI:$driver:database=$database"; 
my $userid = "root"; 
my $password = "password"; 

my $name  = param('name'); 
my $address = param('address'); 
my $city  = param('city'); 
my $occupation = param('occupation'); 
my $age  = param('age'); 

my $dbh = DBI->connect($dsn, $userid, $password, 
    { AutoCommit => 1, RaiseError => 1 }, 
) or die("Couldn't connect to database: $DBI::errstr"); 

my $query = <<'END'; 
INSERT INTO userrecords(Address,Age,City,Name,Occupation) 
       VALUES (  ?, ?, ?, ?,  ?) 
END 

my $statement = $dbh->prepare($query); 
$statement->execute($address, $age, $city, $name, $occupation); 
$dbh->disconnect(); 

my $URL = "http://.....:81/cgi-bin/showdata.cgi"; 
print "Location: $URL\n\n"; 

Обратите внимание, что я удалил много or die заявления, потому что у вас уже есть RaiseError набор к истинному значению.

Для простоты я также (неохотно) включил AutoCommit.

Смежные вопросы