为什么MySQL给我一个语法错误?

时间:2016-09-02 13:53:18

标签: mysql perl

所以我几乎是编码方面的新手,而且我通过试验和错误来学习,这次我尝试使用Perl的数据库,实际上当我只使用3个表头时它很有效(终端, Zeitstempel,Ergebnisnummer)但是当我尝试添加更多标题(Ergebnistext,Transart,Belegnummer,Trace,Betrag,Kartenart,Kartennummer,Entrymode)时,它总是给我一个语法错误,我检查了半个小时但是找不到错误。如果有人知道为什么我会感激你的帮助!这部分代码看起来像这样:

            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执行失败:您的SQL语法出错;   检查与您的MySQL服务器版本对应的文件   在第2行的'')'附近使用正确的语法   C:\ Users \ Desktop \ findlogstamp \ sqlneu.pl lin e 50,第1行。你   您的SQL语法有错误;检查对应的手册   您的MySQL服务器版本,以便在'')'附近使用正确的语法   第2行在C:\用户s \ Desktop \ findlogstamp \ sqlneu.pl第50行,   第1行。

4 个答案:

答案 0 :(得分:6)

您可能会因为以字符串形式传递变量而导致引用错误。您应该使用占位符。

尝试做这样的事情:

{{1}}

我还包括mwp's answer too

同样值得一读Borodins Answer,以便更全面地了解perl中的占位符和SQL。

答案 1 :(得分:3)

我相信&#34;追踪&#34;是MySQL中的保留字。尝试在列名称周围添加反引号。

答案 2 :(得分:1)

必须正确引用SQL表达式中的值。简单的数值不需要引用,我想你使用的前三列 - 终端ID,时间戳和结果号 - 都是数字,这就是它们没有引号的原因

DBI模块提供函数数据库句柄方法quote,它将为您执行此操作(以及quote_identifier对标识符执行相同操作,例如表和列名称) 。但是prepare使用占位符的SQL语句总是更安全,而不是尝试自己将值插入到字符串中。然后,可以在execute调用中提供实际值,wehen DBI会在将所有值插入语句之前隐式调用$dbh->quote

最好prepare语句一次,因为句柄可能会被重复使用。并且无需从%row哈希中提取一系列标量变量 - 可以使用哈希切片直接从哈希中获取正确的字段到{{1}打电话。但是,最好在数组中保留字段名称列表,就像使用execute一样;实际上,您的@headers可能与我的@headers相同,在这种情况下,无需同时定义<{p>}

我在 here document 中使用了SQL字符串。如果你想做同样的事情,那么要小心在结束标记@items之前或之后必须有没有空格,否则它将无法找到

请注意,我已将END_SQL与列表重复运算符join一起使用,以在QSL中生成正确数量的问号占位符。以这种方式执行操作更加安全,以避免错误计数,并允许在不更改SQL语句的情况下更改字段数。如果您愿意,可以x查看已构建的SQL

我希望这会有所帮助

print "$sql\n"

答案 3 :(得分: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();

或者,如果您只想插入一行,可以用一个do()替换所有这些:

$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;