Perl, SQL, DBI: почему моя функция UPDATE не работает? Код и вещи, которые я пробовал внутри

ОБНОВЛЕНИЕ 2: я так и не нашел решения этого. Поскольку код инструктора легко доступен для использования и взлома вместе с нашим собственным, и я уже потратил несколько недель на отладку, я просто создал новую таблицу и начал с его кода, внес изменения и протестировал его по мере продвижения, пока В итоге я получил то, что хотел по функциональности. Если кто-нибудь найдет причину странного поведения, я искренне признателен за то, чтобы узнать, чем это вызвано.

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

ОБНОВЛЕНИЕ: чтобы более четко изложить мой главный вопрос. Исходный пост находится ниже со всем кодом, а также с тем, что я пробовал.

Я разработал свою функцию updateData () для обновления записи. Вместо этого он возвращает свой код ошибки.

sub updateData {
    # and this returns "Update Failed!" for me. I can't figure out why.

    $sql = "UPDATE friendface SET first_name = '$first_name',
        last_name = '$last_name',
        email_address = '$email_address',
        password = '$password'
        WHERE user_id = $user_id;";

    $rc = $dbh->do($sql);
    if ($rc != 1) {
        print "Update Failed!";
    }
}

Ниндзя редактирует, пока я перечитываю этот беспорядок 3:

Код внизу. Извините, если форматирование ужасное или я недостаточно описательный. Я очень старался. Спросите, могу ли я предоставить что-нибудь еще полезное.

Всем привет,

Здесь школьное задание, распечатайте таблицу с записями, которые вы можете редактировать и удалять.

У меня есть HTML-страница с формами для вставки данных, затем Perl-скрипт, который отображает таблицу с кнопками для обновления и удаления. Удалить работает нормально. Весь сценарий работает нормально (ЗА ИСКЛЮЧЕНИЕМ ссылки из блока текста, который вы получаете при прямом доступе к .pl, но в данный момент меня это не волнует) без содержимого моей функции UPDATE. Код функции UPDATE отлично работает построчно в MySQL. Но я не могу заставить функцию updateData с запросом UPDATE работать в моем файле .pl.

Нам разрешен полный доступ к образцу кода инструктора. Я МОГ начать с его страницы, а затем преобразовать ее в свою. Я бы предпочел написать свою страницу, не полагаясь на этот костыль. Однако я сравниваю свой код с его и не понимаю, в чем я ошибаюсь. Насколько я знаю / могу найти документацию, синтаксис выглядит неплохо.

  • Я все равно на всякий случай поигрался с разным синтаксисом. Поместите запятую после последней записи перед моим предложением WHERE, потому что без него оно выглядело неправильно, но, очевидно, без него - это путь. Все, что я прочитал, говорит о том, что текущий синтаксис правильный.

  • Я подумал, что, возможно, он пытался отредактировать user_id, которого не было, но печать user_id показала, что используется правильный.

  • Я думаю, что мой DBI->connect работает, потому что он не возвращает сообщение «Ошибка подключения».

  • Правильная функция, updateData(), выполняется, потому что конечный результат - это код возврата Ошибка обновления, уникальный для этой функции.

  • Я могу отследить код с помощью кнопки «Правка»> «Форма редактирования»> «Подтвердить функцию редактирования»> «Функция updateData»> $ dbh успешно аутентифицируется, do($sql), это мой запрос UPDATE, который выглядит синтаксически правильным. Но почему-то $dbh->do($sql); не соответствует действительности.

  • В функции updateData я подумал, что проблема не в том, что я обновляю только 4 из 6 полей. Ну, 5, так как ключ никогда не будет обновляться. В любом случае, я подумал, что это может как-то сбить его с толку, но добавление строки для обновления имени пользователя не помогло, поэтому я снова вынул ее.

Я действительно пытался разобраться в этом самостоятельно и выдергивал волосы. Это всегда какая-то тупая мелочь. Это интервал? Обычно это не имеет значения, но я знаю, что ENDFORM должен был быть первым и единственным, что поставили на карту, чтобы работать на меня. Но я не знаю никаких правил использования интервалов для этого конкретного кода. Пожалуйста. Укажите мне правильное направление.

Чтобы быть точным, printEditButton() и printDeleteButton() - это код для кнопок редактирования и удаления ...

Таблица DESC, код для html-страницы и скрипт pl следующие:

*********************
*********************
***DESC friendface***
*********************
*********************

Field   Type    Null    Key Default Extra
user_id int(11) NO  PRI NULL    auto_increment
username    char(50)    YES     NULL    
first_name  char(20)    YES     NULL    
last_name   char(20)    YES     NULL    
email_address   char(50)    YES     NULL    
password    char(50)    YES     NULL    




*********************
*********************
*friendFaceForm.html*
*********************
*********************

<table bgcolor='antiquewhite' align=center cellpadding=2>
<form action='friendFaceForm.pl' method=GET>

<tr>
    <td align=right>Username</td>
    <td><input type=text name=username></td>
</tr>

    <tr>
        <td align=right>First Name</td>
        <td><input type=text name=first_name></td>
    </tr>

    <tr>
        <td align=right>Last Name</td>
        <td><input type=text name=last_name></td>
    </tr>


    <tr>
        <td align=right>Email Address</td>
        <td><input type=text name=email_address></td>
    </tr>

    <tr>
        <td align=right>Password</td>
        <td><input type=text name=password></td>
    </tr>

    <tr>
        <td align=center colspan=2> <input type=submit name=action value='Insert Data'></td>
    </tr>


</form>
</table>


*********************
*********************
**friendFaceForm.pl**
*********************
*********************

#!/usr/bin/perl

use CGI qw(:standard);
use DBI;
use warnings;

print "Content-type: text/html\n\n";

$dbh = DBI->connect("DBI:mysql:jwiard1:localhost", "jwiard1", "jwiard1")
    or endProgram("Connection Failed!");

$action = param('action');
$user_id = param('user_id');
$username = param('username');
$first_name = param('first_name');
$last_name = param('last_name');
$email_address = param('email_address');
$password = param('password');

if ($action eq 'Insert Data') {
#$action holds this value coming from the html page
#this happens first

    insertData();
    printTable();

}
elsif ($action eq 'Edit') {
#prints the edit form

    printEditForm();

}
elsif ($action eq 'Confirm Edit') {
#then updateData() runs

    updateData();
    printTable();

}
elsif ($action eq 'Delete') {

    deleteData();
    printTable();

}
elsif ($action eq 'Print Table') {

    printTable();

}
else {

    print "Either you are accessing this file directly or \$action has an unaccounted         for value.<br><br>

    If it's the former, get out of here!<br><br>

    If it's the latter... you're getting sleepy. You're getting verrrry sleepy. When     you reach the end of this sentence, you'll wake up with no memory of this page and a strong     feeling that Joe Wiard's code is perfect.<br><br>

    ...or did you just want to see the table?";

    print "<input type=submit name=action value='Print Table'>";

}







####
#Functions! Yay!
####

sub endProgram {
    my ($msg) = @_;
    print $msg;
    die();
}

sub insertData {
#after inserting data, the user is left to click Edit or Delete
#making $action hold the value of 'Edit' or 'Delete' Go to elsif($action eq 'Edit'

    print "Your data has been saved.";

    $sql = "INSERT INTO friendface SET user_id='$user_id',
        username='$username',
        first_name='$first_name',
        last_name='$last_name',
        email_address='$email_address',
        password='$password'  ;";

        $rc = $dbh->do($sql);
        if ($rc != 1) {
            print "Insert failed!";
        }
}

sub printEditButton {

print "<form>";
print "<input type=hidden name=user_id value='$href->{user_id}'>";
print "<input type=submit name=action value='Edit'>";
print "</form>";

}

sub printDeleteButton {

print "<form>";
print "<input type=hidden name=user_id value='$href->{user_id}'>";
print "<input type=submit name=action value='Delete'>";
print "</form>";

}

sub confirmEdit {



}

sub lookUpRow {

    $sql = "SELECT * FROM friendface WHERE user_id=$user_id;";

    $sth = $dbh->prepare($sql);

    $rc = $sth->execute();

    $href = $sth->fetchrow_hashref();

}

sub printEditForm {
#prints fields for 4 of the values in a record. I don't want the user to be able to
#change their username. They can only edit first and last names, email and password.
#after this, $action either holds 'Confirm Edit' or 'Cancel'. Go to elsif
#($action'Confirm Edit')

    lookUpRow();

    print <<ENDOFFORM;
    <form>
    First Name: <input type=text name=first_name value='$href->{first_name}'> <br>
    Last Name:  <input type=text name=last_name value='$href->{last_name}'> <br>
    Email Address:  <input type=text name=email_address value='$href->{email_address}'>         <br>
    Password:  <input type=text name=password value='$href->{password}'> <br>
    <input type=hidden name=user_id value=$href->{user_id}'> <br>
    <input type=submit value="Confirm Edit" name=action>
    <input type=submit value="Cancel" name=action>
    </form>
ENDOFFORM
#It seems that ENDOFFORM *MUST* be at the beginning of the line. No TABS or SPACES
#preceeding, and NOTHING after. Half an hour of debugging lead me to discovery this
#tidbit that I should have just remembered from class. Or Googled. :P
}

sub updateData {
#and this returns "Update Failed!" for me. I can't figure out why.


    $sql = "UPDATE friendface SET first_name = '$first_name',
        last_name = '$last_name',
        email_address = '$email_address',
        password = '$password'
        WHERE user_id = $user_id   ;";

    $rc = $dbh->do($sql);
    if ($rc != 1) {
        print "Update Failed!";
    }

}

sub deleteData {

    $sql = "DELETE FROM friendface WHERE user_id = $user_id;";

    $rc = $dbh->do($sql);

}

sub printTable {

    $sql = "SELECT * FROM friendface;";
    $sth = $dbh->prepare($sql);
    $rc = $sth->execute();

    $count = 0;

    print "<table>";

    #print header

    while ($href = $sth->fetchrow_hashref() ) {

        $count ++;
        if ($count % 2 == 0) {
            print "<tr bgcolor=lightblue>";
        }
        else {
            print "<tr bgcolor=lightgray>";
        }

        print "<td>";
        print $href->{'user_id'};
        print "</td>";
        print "<td>";
        print $href->{'username'};
        print "</td>";
        print "<td>";
        print $href->{'first_name'};
        print "</td>";
        print "<td>";
        print $href->{'last_name'};
        print "</td>";
        print "<td>";
        print $href->{'email_address'};
        print "</td>";
        print "<td>";
        print $href->{'password'};
        print "</td>";
        print "<td>";
        printEditButton();
        print "</td>";
        print "<td>";
        printDeleteButton();
        print "</td>";

        print "</tr>";
    }

    print "</table>";

person user16345    schedule 22.11.2013    source источник
comment
Что он делает, чего вы не ожидаете / не понимаете?   -  person Jim Garrison    schedule 22.11.2013
comment
Извините, если это было непонятно. После редактирования записи и нажатия кнопки «Подтвердить редактирование» запись не обновляется, появляется сообщение «Ошибка обновления»! и таблица снова распечатывается. Я также подтвердил, что фактическая таблица в базе данных не обновляется. Функция updateData () возвращает ошибку обновления! сообщение об ошибке. Я не понимаю, что не так с моей функцией updateData (), и я подозреваю, что в этом проблема. Или с остальной частью моего кода, если это проблема.   -  person user16345    schedule 22.11.2013
comment
Основная проблема в том, что я ожидал $ dbh- ›do ($ sql); в updateData (), чтобы оно было истинным и запись обновлялась. На самом деле происходит $ dbh- ›do ($ sql); выходит false, и я получаю код возврата Ошибка обновления !.   -  person user16345    schedule 22.11.2013
comment
updateData () выполняет инструкцию SQL в вашей базе данных. Если база данных возвращает ошибку, начните с нее расследование. Какой именно запрос вы ожидаете от кода Perl? Что вы видите, когда выполняете тот же запрос с помощью командной строки mysql < / а>?   -  person Iain Samuel McLean Elder    schedule 22.11.2013
comment
$ dbh- ›do ($ sql) - это код как в функции updateData (), так и в исходной функции insertData (), которая при возврате значения true выполняет запрос INSERT или UPDATE. Он возвращает true для запроса INSERT, но возвращает false для запроса UPDATE. Запрос UPDATE не обновляет каждое поле в таблице. Интересно, возникает ли моя проблема как-то от этого.   -  person user16345    schedule 03.12.2013
comment
Каково фактическое значение $rc, когда ОБНОВЛЕНИЕ ведет себя не так, как вы ожидаете? Это определено? Это 0E0?   -  person pilcrow    schedule 06.12.2013
comment
Во-первых: используйте строгое; каждый раз, когда вы пишете на Perl более длинный код, чем однострочный. Если необходимые исправления не устраняют ошибку, вернитесь снова.   -  person Vesa Karjalainen    schedule 14.12.2016


Ответы (1)


Из документации DBI кажется, что метод do магия с возвращаемым значением:

do

Если вы выполняете UPDATE, INSERT или DELETE, данные, возвращаемые из базы данных, не поступают, поэтому есть короткий путь. Ты можешь сказать

$ dbh-> do ('УДАЛИТЬ ОТ людей ГДЕ старше 65 лет'); например, и DBI подготовит оператор, выполнит его и завершит. do возвращает истинное значение в случае успеха и ложное значение в случае неудачи. Фактически, в случае успеха он возвращает количество затронутых строк. В этом примере он вернет количество фактически удаленных строк. (DBI использует волшебный трюк, так что полученное значение истинно даже тогда, когда оно равно 0. Это странно, потому что 0 обычно ложно в Perl. Но это удобно, потому что вы можете использовать его либо как число, либо как истинное или -false код успеха, и он работает в обоих направлениях.)

Вы уверены, что обновление не сработало? Затем выполните выбор, чтобы перепроверить. Возможно, вы неправильно интерпретируете код возврата.

person Blake Caldwell    schedule 22.11.2013
comment
Я могу подтвердить с помощью дружеского интерфейса SELECT * FROM, что мои записи не обновляются. Однако это интересное поведение DBI. - person user16345; 25.11.2013
comment
И вы распечатали sql обновления, и это кажется правильным? Как насчет того, чтобы взять этот SQL и запустить его самостоятельно из консоли sql, просто чтобы убедиться, что он полностью действителен? - person Blake Caldwell; 25.11.2013
comment
Именно так я и поступил: я пропустил проверку страницы и сразу перешел в консоль. ›Mysql› use jwiard1 ›select * from friendface; - person user16345; 25.11.2013
comment
Я имел в виду, распечатайте инструкцию обновления из скрипта, чтобы убедиться, что она действительна, со всеми правильно введенными параметрами. Скопируйте тот оператор обновления SQL и попробуйте выполнить его в консоли. - person Blake Caldwell; 25.11.2013
comment
Я могу взять код из функции updateData () и ввести его построчно в консоль mysql, чтобы получить желаемые результаты. Обновление происходит как положено. Я могу запустить весь свой Perl-скрипт за вычетом только кода внутри функции updateData (), и он тоже работает должным образом. Но когда я помещаю, казалось бы, действительный код UPDATE mysql в функцию updateData () и пытаюсь запустить все вместе, $ dbh- ›do ($ sql) внутри функции updateData () возвращает false, что приводит к тому, что функция updateData () возвращает свой код ошибки и, как я убедился, таблица не обновляется. - person user16345; 03.12.2013