Perl DBD:ODBC 在准备 sql 服务器插入语句时抛出 "does not yet support binding a named parameter more than once"
Perl DBD:ODBC throwing "does not yet support binding a named parameter more than once" when preparing sql-server insert statement
Perl DBD::ODBC 从 sql 服务器插入语句
抛出错误
DBD::ODBC does not yet support binding a named parameter more than once
当不打算在此脚本中绑定参数时。我试过自己回答这个问题,并继续这样做,但没有找到类似问题的答案。
我有一个脚本可以将 csv(包含日期时间、guid 和 comments/message 字符串的组合)加载到数据库中。如果需要,我在下面包含了我的部分脚本以供进一步分析。在 csv 中输入 350,000 多行(大约 20 列)之后,它似乎被这个错误挂断了,但我一直无法弄清楚到底是什么导致了它。
我试过设置
$self->{dbh}->{odbc_ignore_named_placeholders} = 1;
但没有成功克服该错误。 csv 中的所有值都用单引号括起来,但其中一些值是包含 either/both :
和 ?
.
的字符串
在这种情况下,我不打算使用绑定参数或命名占位符 -- 只是为了将原始数据导入数据库。
由于故障排除,脚本的这一部分打印了很多内容。整个脚本还没有 intentionally/unintentionally 优化——我的目标是让它正常工作。 善良点。
这将实例化“Connection”对象。由于连接是在这里建立的,并分配给 $self->{dbh}
,我应该可以将 1 分配给 {odbc_ignore_named_placeholders}
,但它似乎不起作用。
sub New {
my $class = shift;
my $self = {
dbh => DBI->connect( $dsn ),
dropIfExists => 1, # 1 == drop, 0 == do not drop or create
debug => 1, # 1 == enabled, 0 == disabled
};
$self->{dbh}->{odbc_ignore_named_placeholders} = 1;
bless $self, $class;
return $self;
}
这是在插入语句中准备行的重要部分:
while ( my $row = $csv->getline( $fh ) ) {
my @fields = @{$row};
my @newline = ();
for ( @fields ) {
my $str = $_;
$str =~ s/'+/''/;
my $newString = "'" . $str . "'";
print $newString.NewLine;
push( @newline, $newString );
}
my $line = join( ",", @newline );
$values .= "(" . $line . "),";
$MasterLineCount++;
print FancyLine;
print "MasterLineCount: " . $MasterLineCount . NewLine;
print FancyLine;
$count++;
print FancyLine;
print "Line count: ".$count.NewLine;
print FancyLine;
# sql server allows a maximum of 1000 values (rows) in a
# single insert statement, so this stops the loop, and
# prepares/executes the query. if the loop hits the end of
# the file with a count < 999, it drops out of the
# while loop, and checks if count > 0, if it is, it
# prepares/executes the statement for the remaining
# rows/lines
if ( $count == 999 ) {
$statementCount++;
print FancyLine;
print "Statement Count: " . $statementCount . NewLine;
print FancyLine;
my $insertStmt = "insert into " . $db_name . ".dbo." . $tableName . " (" . $colNames . ") values " . $values;
my $chopTrailingComma = chop( $insertStmt );
# print "Insert Statement: ".NewLine;
# print FancyLine;
# print $insertStmt.NewLine;
# print FancyLine;
# load table
$self->ExecuteStmt( $insertStmt );
#reset values string
$values = "";
#reset count
$count = 0;
}
}
if ( $count > 0 ) {
$statementCount++;
print FancyLine;
print "Statement Count: " . $statementCount . NewLine;
print FancyLine;
my $insertStmt = "insert into " . $db_name . ".dbo." . $tableName . " (" . $colNames . ") values " . $values;
my $chopTrailingComma = chop( $insertStmt );
# load table
$self->ExecuteStmt( $insertStmt );
#reset values string
$values = "";
#reset count
$count = 0;
}
为清楚起见,这是 ExecuteStmt()
:
sub ExecuteStmt {
my $self = shift;
my $stmt = shift;
$self->{sth} = $self->{dbh}->prepare( $stmt );
$self->{sth}->execute or die "$stmt".NewLine().FancyLine().$self->{sth}->errstr;
}
好吧,我想出了一个解决方法,它与 dbi 模块无关。创建新的Text::CSV对象时,传入如下参数:
verbatim => 1,
这是我的 Text::CSV 构造函数现在的样子:
my $csv = Text::CSV_XS->new( { binary => 1,
eol => $/,
always_quote => 1,
verbatim => 1,
skip_empty_rows => 1
} );
来自文档 Text::CSV:
> This is a quite controversial attribute to set, but makes some hard
> things possible.
>
> The rationale behind this attribute is to tell the parser that the
> normally special characters newline (NL) and Carriage Return (CR) will
> not be special when this flag is set, and be dealt with as being
> ordinary binary characters. This will ease working with data with
> embedded newlines.
>
> When verbatim is used with "getline", "getline" auto-chomp's every line.
如果我发现与此更改相关的任何意外后果,我会更新此 question/answer。
Perl DBD::ODBC 从 sql 服务器插入语句
抛出错误DBD::ODBC does not yet support binding a named parameter more than once
当不打算在此脚本中绑定参数时。我试过自己回答这个问题,并继续这样做,但没有找到类似问题的答案。
我有一个脚本可以将 csv(包含日期时间、guid 和 comments/message 字符串的组合)加载到数据库中。如果需要,我在下面包含了我的部分脚本以供进一步分析。在 csv 中输入 350,000 多行(大约 20 列)之后,它似乎被这个错误挂断了,但我一直无法弄清楚到底是什么导致了它。
我试过设置
$self->{dbh}->{odbc_ignore_named_placeholders} = 1;
但没有成功克服该错误。 csv 中的所有值都用单引号括起来,但其中一些值是包含 either/both :
和 ?
.
在这种情况下,我不打算使用绑定参数或命名占位符 -- 只是为了将原始数据导入数据库。
由于故障排除,脚本的这一部分打印了很多内容。整个脚本还没有 intentionally/unintentionally 优化——我的目标是让它正常工作。 善良点。
这将实例化“Connection”对象。由于连接是在这里建立的,并分配给 $self->{dbh}
,我应该可以将 1 分配给 {odbc_ignore_named_placeholders}
,但它似乎不起作用。
sub New {
my $class = shift;
my $self = {
dbh => DBI->connect( $dsn ),
dropIfExists => 1, # 1 == drop, 0 == do not drop or create
debug => 1, # 1 == enabled, 0 == disabled
};
$self->{dbh}->{odbc_ignore_named_placeholders} = 1;
bless $self, $class;
return $self;
}
这是在插入语句中准备行的重要部分:
while ( my $row = $csv->getline( $fh ) ) {
my @fields = @{$row};
my @newline = ();
for ( @fields ) {
my $str = $_;
$str =~ s/'+/''/;
my $newString = "'" . $str . "'";
print $newString.NewLine;
push( @newline, $newString );
}
my $line = join( ",", @newline );
$values .= "(" . $line . "),";
$MasterLineCount++;
print FancyLine;
print "MasterLineCount: " . $MasterLineCount . NewLine;
print FancyLine;
$count++;
print FancyLine;
print "Line count: ".$count.NewLine;
print FancyLine;
# sql server allows a maximum of 1000 values (rows) in a
# single insert statement, so this stops the loop, and
# prepares/executes the query. if the loop hits the end of
# the file with a count < 999, it drops out of the
# while loop, and checks if count > 0, if it is, it
# prepares/executes the statement for the remaining
# rows/lines
if ( $count == 999 ) {
$statementCount++;
print FancyLine;
print "Statement Count: " . $statementCount . NewLine;
print FancyLine;
my $insertStmt = "insert into " . $db_name . ".dbo." . $tableName . " (" . $colNames . ") values " . $values;
my $chopTrailingComma = chop( $insertStmt );
# print "Insert Statement: ".NewLine;
# print FancyLine;
# print $insertStmt.NewLine;
# print FancyLine;
# load table
$self->ExecuteStmt( $insertStmt );
#reset values string
$values = "";
#reset count
$count = 0;
}
}
if ( $count > 0 ) {
$statementCount++;
print FancyLine;
print "Statement Count: " . $statementCount . NewLine;
print FancyLine;
my $insertStmt = "insert into " . $db_name . ".dbo." . $tableName . " (" . $colNames . ") values " . $values;
my $chopTrailingComma = chop( $insertStmt );
# load table
$self->ExecuteStmt( $insertStmt );
#reset values string
$values = "";
#reset count
$count = 0;
}
为清楚起见,这是 ExecuteStmt()
:
sub ExecuteStmt {
my $self = shift;
my $stmt = shift;
$self->{sth} = $self->{dbh}->prepare( $stmt );
$self->{sth}->execute or die "$stmt".NewLine().FancyLine().$self->{sth}->errstr;
}
好吧,我想出了一个解决方法,它与 dbi 模块无关。创建新的Text::CSV对象时,传入如下参数:
verbatim => 1,
这是我的 Text::CSV 构造函数现在的样子:
my $csv = Text::CSV_XS->new( { binary => 1,
eol => $/,
always_quote => 1,
verbatim => 1,
skip_empty_rows => 1
} );
来自文档 Text::CSV:
> This is a quite controversial attribute to set, but makes some hard
> things possible.
>
> The rationale behind this attribute is to tell the parser that the
> normally special characters newline (NL) and Carriage Return (CR) will
> not be special when this flag is set, and be dealt with as being
> ordinary binary characters. This will ease working with data with
> embedded newlines.
>
> When verbatim is used with "getline", "getline" auto-chomp's every line.
如果我发现与此更改相关的任何意外后果,我会更新此 question/answer。