2016-09-02 4 views
0

, поэтому я довольно большой новичок в кодировании, и я доволен обучением Trial и ошибкой, на этот раз я пытаюсь работать с DB с Perl, на самом деле он хорошо работает, когда я просто использую 3 заголовка таблицы (Terminal, Zeitstempel , Ergebnisnummer), но когда я пытаюсь добавить больше заголовков (Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode), он всегда дает мне синтаксическую ошибку, и я проверил полчаса, но не смог найти ошибку. Если кто-нибудь знает, почему я буду благодарен за вашу помощь! эта часть моего кода выглядит так:Почему MySQL дает мне синтаксическую ошибку?

  foreach $file (@file) 
     { 
      $currentfile = "$currentdir\\$file"; 
      open(zloop, "<", $currentfile) or die "Failed to open file: $!\n"; 
        while (<zloop>) { 
        my %row; 
        chomp; 
        @row{@headers} = split /;/; 
        my $tid = $row{'tid'}; 
        my $zeit = $row{'zeit'}; 
        my $ergebnisnummer = $row{'ergebnisnummer'}; 
        my $ergebnistext = $row{'ergebnistext'}; 
        my $transart = $row{'transart'}; 
        my $belegnummer = $row{'belegnummer'}; 
        my $trace = $row{'trace'}; 
        my $betrag = $row{'betrag'}; 
        my $kartenart = $row{'kartenart'}; 
        my $kartennummer = $row{'kartennummer'}; 
        my $entrymode = $row{'entrymode'}; 

    my $sth = $dbh->prepare("INSERT INTO `teso`(Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode) 
    values ($tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode)"); 
    $sth->execute() or die $DBI::errstr; 
    $sth->finish(); 

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

DBD :: mysql :: st execute failed: У вас возникла ошибка в синтаксисе SQL; проверьте версию, соответствующую вашей версии сервера MySQL, для , для синтаксиса справа от строки '') 'в строке 2 на C: \ Users \ Desktop \ findlogstamp \ sqlneu.pl lin e 50, строка 1. Вы: ошибка в синтаксисе SQL; проверьте руководство, которое соответствует вашей версии сервера MySQL для правильного синтаксиса, чтобы использовать рядом с «»)»в строке 2 в C: \ Пользователя \ Desktop \ findlogstamp \ sqlneu.pl линии 50, линии 1.

+0

Что ошибка? – mwp

+2

Построение оператора SQL путем интерполяции переменных в строку, как правило, очень плохая идея. Подробности см. В [Bobby Tables] (http://bobby-tables.com/). –

ответ

7

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

Попробуйте делать что-то вроде этого, вместо:

my $sth = $dbh->prepare('INSERT INTO `teso`(Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, 
    Transart, Belegnummer, `Trace`, Betrag, Kartenart, Kartennummer, Entrymode) 
    values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); 
$sth->execute($tid, $zeit, $ergebnisnummer, $ergebnistext, 
    $transart, $belegnummer, $trace, $betrag, $kartenart, 
    $kartennummer, $entrymode) or die $DBI::errstr; 

Я также включил mwp's answer too.

Также полезно прочитать Borodins Answer для более тщательного подхода к заполнителям и SQL внутри perl.

+0

Это сработало, спасибо, не могли бы вы объяснить, что именно случилось? мои переменные являются в основном полными числами, но 2-3 являются либо строками, либо вариантными типами, я думал, что их маркировка с '' будет достаточно –

+1

Вам нужно будет процитировать вещи именно для MySQL, чтобы быть счастливыми их обработать. Используя переменные связывания ('?' В 'prepare()'), а затем передача ваших значений в 'execute()' будет выполнять «тяжелый подъем» цитаты, где это необходимо для вас. Обычно рекомендуется использовать переменные для операторов. –

+0

И для записи я имел в виду заполнители, а не связывал переменные, они разные вещи! –

3

Я считаю, что «трассировка» является зарезервированным словом в MySQL. Попробуйте добавить обратные ссылки вокруг имени столбца.

+0

Не понял бы, что он может иметь только имена столбцов внутри 'INSERT INTO foo (...)' construct? – simbabque

+1

Было бы хорошо, но, к сожалению, нет. – mwp

+0

ye, у меня была ошибка, прежде чем это было вызвано столбцом «Terminal-ID», -ID вызвало проблемы, мне потребовалось 1 час, чтобы понять, поэтому я попытался поместить трассировку в '' уже, но это не сработало грустно, спасибо за хороший ответ, хотя! –

0

Я думаю, ошибка в том, что обратные метки вокруг teso интерполируются perl. В любом случае, интерполяция значений в строку запроса - очень плохая идея. Вы можете заменить кавычки вокруг вашего запроса одиночными кавычками (чтобы устранить нежелательную интерполяцию) и заменить значения, которые нужно вставить с помощью заполнителей. Затем вы должны передать фактические значения методу execute(). Как это:

my $sth = $dbh->prepare('INSERT INTO teso(Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode) 
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'); 
$sth->execute($tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode) or die $DBI::errstr; 
$sth->finish(); 

или, если вы хотите вставить только одну строку, вы можете заменить все это с помощью одного до():

$dbh->do('INSERT INTO teso(Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', undef, 
    $tid, $zeit, $ergebnisnummer, $ergebnistext, $transart, $belegnummer, $trace, $betrag, $kartenart, $kartennummer, $entrymode) or die $DBI::errstr; 
+2

Ваше первое предположение неверно. Perl ничего не запускает в backticks, который находится внутри двойных кавычек. Интерполяция не работает. – simbabque

+0

@simbabque, ты абсолютно прав! Обновленный ответ. –

1

значений в выражении SQL должны быть указаны правильно , Простым числовым значениям не требуется кавычки, и я думаю, что первые три столбца, которые вы использовали - идентификатор терминала, отметка времени и номер результата, - все номера, поэтому они работали без котировок.

Модуль DBI обеспечивает метод обработки базы данных функций quote, который сделает это за вас (а также quote_identifier, что делает то же самое для идентификаторов, таких как имена таблиц и столбцов).Однако всегда гораздо безопаснее prepare оператор SQL с заполнителями вместо того, чтобы пытаться интерполировать значения в строку самостоятельно. Затем фактические значения могут быть представлены в execute вызова Wehen DBI неявно называют $dbh->quote на все значения, прежде чем вставлять их в заявление

Это также лучше, чтобы prepare заявление только раз, как ручка может затем использовать повторно. И нет необходимости извлекать серию скалярных переменных из вашего %row хеш - хэш-фрагмент можно использовать для извлечения правильных полей прямо из хэша в вызов execute. Однако лучше сохранить список имен полей в массиве, как и в случае с @headers; на самом деле ваш @headers может быть такой же, как и мои @items, в этом случае нет необходимости определять как

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

Следует заметить, что я использовал join вместе со списком оператор повторения x, чтобы получить точное количество заполнителей вопросительных знаков в QSL. Гораздо безопаснее делать это таким образом, чтобы избежать ошибок и разрешить изменение количества полей без изменения инструкции SQL. Вы можете print "$sql\n", чтобы увидеть SQL, который был построен, если вы хотите

Я надеюсь, что это помогает

my @items = qw/ 
    tid zeit ergebnisnummer ergebnistext transart 
    belegnummer trace betrag kartenart kartennummer entrymode 
/; 

my $sql = sprintf <<END_SQL, join ', ', ('?') x @items; 
INSERT INTO teso (
    Terminal, Zeitstempel, Ergebnisnummer, Ergebnistext, Transart, 
    Belegnummer, Trace, Betrag, Kartenart, Kartennummer, Entrymode 
) 
VALUES (%s) 
END_SQL 

my $insert = $dbh->prepare($sql); 

for my $file (@file) { 

    my $current_file = "$currentdir\\$file"; 

    open my $fh, '<', $current_file or die qq{Unable to open "$current_file" for input: $!}; 

    while (<$fh>) { 

     my %row; 
     @row{@headers} = split /;/; 

     $insert->execute(@row{@items}) or die $sth->errstr; 
    } 
} 
Смежные вопросы