代码之家  ›  专栏  ›  技术社区  ›  friedo

mysql注释导致perl dbi绑定参数计数混乱

  •  1
  • friedo  · 技术社区  · 15 年前

    我有下面的Perl代码,可以调用DBI:

    my $artsql = q{ *** SNIP A BUNCH OF SQL ***
                    where a.article_id != ?
                          and at.type_name != 'List Element'   -- don't get list children
                          and aw.flowstate = 'Published'
                          and a.visible_as_article = 1 }
          . ( $filter ? q{and ch.channel_id = ?
                          and cat.category_id = ? }
                      : '' ) 
             . q{order by a.publish_date desc
                    limit 5};
    
    my @bind = ( $article );
    push @bind, ( $channel_id, $category_id ) if $filter;
    
    my $articles = $dbh->selectall_arrayref( $artsql, { Slice => { } }, @bind );
    

    什么时候? $filter 打开时,此代码将因错误而消失:

    DBD::mysql::db selectall_arrayref failed: called with 3 bind variables when 1 are needed
    

    起初,我认为这是字符串中间三元条件的问题(我多次被那个错误咬过),但它是正确的。转储一些调试值表明查询和 @bind 数组构造正确。

    然后我注意到查询在 第一 绑定变量,所以我一时兴起删除了它。噗,成功了!

    根据MySQL docs on comments ,

    MySQL Server支持三种注释样式: 从___字符到行尾。 从_--226;_序列到测线末端。在MySQL中,--(双破折号)注释样式要求第二个破折号后面至少有一个空格或控件 字符(如空格、制表符、换行符等)。

    因为评论 -- 接下来是一个空格,并且(大概)以行尾结束,为什么MySQL会阻塞?DBI在幕后用换行符或空格做了什么奇怪的事情吗?

    3 回复  |  直到 15 年前
        1
  •  5
  •   Schwern    15 年前

    您的SQL或Perl代码看起来没有任何问题。

    这可能是dbi、dbd::mysql或mysql本身的错误。调试这个问题的第一步是找出哪个位有故障。所以,从消除变量开始。

    从消除绑定变量开始,硬编码一些值,看看过程是否正确。如果不是,那么它可能是dbd::mysql或dbi中的一个bug。首先尝试更新这两个版本,看看问题是否已解决。如果不起作用, report the bug . 注意有一个 similar comment parsing bug 所以很可能是dbd::mysql。(你确定 do not get list children 而不是 don't get list children ?)

    接下来从公式中去掉perl。在mysql shell中运行查询(使用\e打开一个编辑器)。有同样的问题吗?如果是这样,那么mysql就是错的。再次尝试升级。

        2
  •  1
  •   Dan    15 年前

    我在其他地方也看到过类似的事情。最有可能的情况是,在不同的层中的某个地方(Schwern是对的,你必须挖掘看看是哪一层),一些代码正在将换行符转换为空格,这在当时看来是一个合理的原因,因此你的评论占据了整个查询的其余部分。

    我给人们的建议是不要在SQL中使用单行注释,除非使用命令行或其他专用客户机。只不过涉及了太多的层和隐藏bug的机会。

        3
  •  1
  •   Anna Graham    15 年前

    评论里面的单引号把它搞砸了。 不知道是什么导致了这个错误。 把“不要最后一个孩子”改为“不要最后一个孩子”,你的问题就会消失。