【问题标题】:perl/dbi/sql stumped by "operation must use an updatable query" errorperl/dbi/sql 被“操作必须使用可更新查询”错误所困扰
【发布时间】:2013-07-20 21:04:36
【问题描述】:

我有一个 Perl 脚本,它构建了一个 sql cmd 以将 MS Access db 中某个表中的某些字段设置为 NULL(抱歉)。 这是一个简化的模型。

my $nonKeyFields_hashref = { "country" => "ZZZ",
                             "address3" => "FOO"
                           };
my $keyFields_hashref = { "address1" => "1212 O'Mally Street",    # embedded single quote here is causing the problem
                          "client ID" => "1234567"
                        };
my $sqlCmd = "UPDATE myTable SET ";
$sqlCmd .= join( ", " , map{ "[?} = NULL "} keys $nonKeyFields_hashref;
$sqlCmd .= " WHERE ";
$sqlCmd .= join( " AND " , map{ "[?} = ? "} keys $keyFields_hashref;

# sqlCmd contains "UPDATE myTable SET [?] = NULL, [?} = NULL WHERE [?] = ? AND [?] = ?"

$sth = $dbh->prepare( $sqlCmd);
if( !defined( $sth)) {
  _pushErrorMsg("sth failed to define - ".$DBI::errstr);
  $errorHit = 1;
} else {
  my @cmd_arry = ();
  push( @cmd_arry, $_ ) for keys $nonKeyFields_hashref;
  push( @cmd_arry, $_ , $keyFields_hashref->{$_} ) for keys $keyFields_hashref;
  print Dumper( @cmd_arry);

  # dumper shows @cmd_arry contains ("country", "address3", "address1", "1212 O'Mally Street", "client ID", "1234567")
  # which is six elements, which jibes with the query's question-marks

  $sth->execute( @cmd_arry);    # errors here with the given message
  ....
}

当数据不包含讨厌的嵌入式单引号时,此代码效果很好。我希望绑定能解决这个问题,但没有这样的运气。

有人有解决这个单引号问题的方法吗?

提前致谢,

仍在学习史蒂夫。

【问题讨论】:

    标签: sql perl ms-access dbi


    【解决方案1】:

    该代码包含语法错误,原因是 a) 连接调用中缺少关闭 ) b) 缺少对 Data::Dumper 的使用。我假设您使用的是最近的 Perl,因为您似乎期望 $hash_references 会自动取消引用。

    数据库引擎接受列名参数是不寻常的 - 这绝对不适用于大多数数据库。

    据我所知,您所说的单引号对该脚本没有影响-它只是在 else 中为 SQL 语句推送了太多参数而被破坏了。 SQL 语句需要 4 个列名,而您推送 4 个列名和 2 个值。

    我想你的意思是“push(@cmd_arry, $_, $keyFields_hashref->{$_}”是“push(@cmd_arry, $_”。

    【讨论】:

    【解决方案2】:

    一些轻微的重构就成功了:

    $sqlCmd = "UPDATE [$tableName] SET ";
    $sqlCmd .= join( ", ", map { "[$_] = NULL "} keys $nonKeyFields_hashref);
    $sqlCmd .= " WHERE ";
    $sqlCmd .= join( " AND ", map { "[$_] = ? "} keys $keyFields_hashref);
    # sneaky values may contain embedded single-quotes for GoGo's , 4343 Little's Court, etc
    
    my $sth = undef;
    $sth = $dbh->prepare( $sqlCmd);
    if( !defined( $sth)) {
      _pushErrorMsg("sth failed to define - ".$DBI::errstr);
      $errorHit = 1;
    } else {
      my @cmd_arry = ();
      push( @cmd_arry, $keyFields_hashref->{$_} )  for keys( $keyFields_hashref);
      print Dumper( @cmd_arry);
      my $resultCnt = $sth->execute( @cmd_arry);
      if( my $errorMsg = $dbh->errstr ) 
     ....
    

    感谢所有回复的人!

    还在学习的史蒂夫

    【讨论】:

    • 这就是我所说的,但你没有将我的任何答案标记为答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2010-09-15
    • 1970-01-01
    相关资源
    最近更新 更多