繁体   English   中英

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

[英]Why is MySQL giving me a syntax error?

所以我在编码方面是个新手,我有点试错了,这次我尝试使用Perl使用DB,实际上当我只使用3个表头(Terminal,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语法有错误; 在C:\\ Users \\ Desktop \\ findlogstamp \\ sqlneu.pl lin e 50,第1行的第2行中,检查与您的MySQL服务器版本相对应的手册,以在'')'附近使用正确的语法。您的SQL语法; 在第2行的C:\\ User s \\ Desktop \\ findlogstamp \\ sqlneu.pl第50行第1行中,检查与MySQL服务器版本相对应的手册,以在``)'附近使用正确的语法。

由于将变量作为字符串传递,可能会引起引用错误。 您应该改为使用占位符。

尝试做这样的事情:

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的答案

还值得花时间阅读《 Borodins答案》 ,以获得在Perl中处理占位符和SQL的更彻底的方法。

我相信“ trace”是MySQL中的保留字。 尝试在列名称周围添加反引号。

SQL表达式中的值必须正确引用。 简单的数字不需要用引号引起,并且我想象您使用的前三列-终端ID,时间戳和结果号-都是数字,这就是为什么它们不用引号就可以工作的原因

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

这也是最好prepare一份声明中只有一次 ,当手柄然后可以重复使用。 无需从%row哈希中提取一系列标量变量- 哈希切片可用于直接从哈希中获取正确的字段,并execute调用。 但是,最好像使用@headers一样在数组中保留字段名称的列表。 实际上,您的@headers可能与我的@items相同,在这种情况下,无需定义两者

我已将此处文档用于SQL字符串。 如果要执行相同的操作,请注意结束标记END_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;
    }
}

我认为,错误是因为 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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM