【问题标题】:Perl DBD:ODBC throwing "does not yet support binding a named parameter more than once" when preparing sql-server insert statementPerl DBD:在准备 sql-server 插入语句时,ODBC 抛出“不支持多次绑定命名参数”
【发布时间】:2021-07-26 10:33:20
【问题描述】:

Perl DBD::ODBC 从 sql server 插入语句抛出错误

DBD::ODBC does not yet support binding a named parameter more than once

当不打算在此脚本中绑定参数时。我试过自己回答这个问题,并继续这样做,但没有任何运气回答类似的问题。

我有一个脚本可以将 csv(包含日期时间、guid 和 cmets/消息字符串的组合)加载到数据库中。如果需要,我在下面包含了我的脚本的一部分以供进一步分析。在 csv 中超过 350,000 行(大约 20 列)后,它似乎被这个错误挂断了,但我一直无法弄清楚究竟是什么原因造成的。

我试过设置 $self->{dbh}->{odbc_ignore_named_placeholders} = 1; 但没有成功克服这个错误。 csv 中的所有值都用单引号括起来,但其中一些值是包含:? 之一/两者的字符串。

在这种情况下,我不打算使用绑定参数或命名占位符 - 只是为了将原始数据输入数据库。

由于故障排除,在这部分脚本中有相当多的打印。整个脚本还没有被有意/无意地优化——我的目标是让它工作。 善良。

这会实例化“连接”对象。由于在这里建立连接,并分配给$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;
}

【问题讨论】:

标签: sql sql-server perl odbc


【解决方案1】:

好的,我想出了一个解决方法,它与 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.

如果我发现与此更改有关的任何意外后果,我将更新此问题/答案。

【讨论】:

    猜你喜欢
    • 2013-06-15
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多