Ошибка perl/dbi/sql в результате ошибки "операция должна использовать обновляемый запрос"
У меня есть Perl-скрипт, который создает sql cmd для установки определенных полей в NULL в определенной таблице в базе данных MS Access (извините). Вот упрощенный макет.
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
....
}
этот код прекрасно работает, когда данные НЕ содержат неприятных встроенных одинарных кавычек. Я надеялся, что переплет решит эту проблему, но не повезло.
У кого-нибудь есть решение этой проблемы с одинарными кавычками?
Заранее спасибо,
Все еще учусь, Стив.
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 )
....
Спасибо всем, кто откликнулся!
Все еще учусь Стив
Этот код содержит синтаксические ошибки из-за: а) отсутствия закрытия) в вызовах соединения, б) отсутствия использования Data::Dumper. Я предполагаю, что вы используете недавний Perl, так как вы, похоже, ожидаете, что $hash_references автоматически разыменовывается.
Механизм базы данных обычно принимает параметры для имен столбцов - это определенно не будет работать с большинством баз данных.
Насколько я вижу, одиночная кавычка, о которой вы говорите, не оказывает никакого влияния на этот сценарий - она просто разбита по отношению к коду в другом, выдвигая слишком много параметров для оператора SQL. В операторе SQL требуется 4 имени столбца, а вы нажимаете 4 имени столбца и 2 значения.
Я предполагаю, что вы имели в виду " push( @cmd_arry, $_, $keyFields_hashref->{$_}" как "push( @cmd_arry, $_").