Perl、DBI MS SQL:无法绑定未知占位符

Perl, DBI MS SQL: Can't bind unknown placeholder

我在 RedHat 机器上安装了 Perl、DBI 和 ODBC 驱动程序 运行。我从一个非常非常最近的姐妹问题中知道 ODBC 连接正在工作。我对查询中的第一个 bind_param 有疑问。我收到错误:

Can't bind unknown placeholder '1' at ./script.pl line 361.

该部分代码如下所示:

326:  sub isStaff {
327:      my ($MSdbh, $PersonLoginID, $start, $end) = @_;
328:
329:      my $sth = undef;
330:
331:      my $result = undef;
332:
333:      my $tmp = <<EOF;
334:  SELECT
335:          P.PersonLoginID
336:  FROM
337:          Personnel.Persons AS P
338:          INNER JOIN Personnel.Memberships AS M ON M.PersonId = P.PersonId
339:          INNER JOIN Personnel.Groups AS G ON G.GroupId = M.GroupId
340:  WHERE
341:      UPPER(P.PersonLoginID) = UPPER('?')
342:          AND (G.GroupAbbv = 'MyGroup'
343:                  OR G.GroupAbbv = 'SubGroup1'
344:                  OR G.GroupAbbv = 'SubGroup2')
345:          AND (M.StartDate <= '?'
346:                  OR M.StartDate BETWEEN '?' AND '?')
347:          AND (M.EndDate >= '?'
348:                  OR M.EndDate IS NULL)
349:  EOF
350:
351:  $MSdbh->trace(2);
352:
353:      if ( !( $sth = $MSdbh->prepare($tmp) ) ) {
354:                  die "DB prepare failed";
355:          }
356:
357:      print STDERR "$PersonLoginID\n";
358:      print STDERR "$start\n";
359:      print STDERR "$end\n";
360:
361:          $sth->bind_param( 1, $PersonLoginID, SQL_VARCHAR )
362:                  || die "bind_param 1:" . $sth->errstr;
363:          $sth->bind_param( 2, $start, SQL_DATETIME )
364:                  || die "bind_param 2:" . $sth->errstr;
365:          $sth->bind_param( 3, $start, SQL_DATETIME )
366:                  || die "bind_param 3:" . $sth->errstr;
367:          $sth->bind_param( 4, $end, SQL_DATETIME )
368:                  || die "bind_param 4:" . $sth->errstr;
369:          $sth->bind_param( 5, $end, SQL_DATETIME )
370:                  || die "bind_param 5:" . $sth->errstr;
371:
372:          if ( !( $sth->execute() ) ) {
373:                  die "DB execute failed";
374:          }
375:
376:          $sth->bind_col(1, $PersonLoginID )
377:                  || die "bind_columns:" . $sth->errstr;
378:
379:      my $i = 0;
380:      for ($i = 0; $sth->fetch; $i++) {
381:          ;
382:      }
383:
384:      $sth->finish;
385:
386:      if ($i == 1) {
387:          return 1;
388:      } else {
389:          return 0;
390:      }
391:  }

DBI->trace() 和诊断打印输出是:

    DBI::db=HASH(0x35c5420) trace level set to 0x0/2 (DBI @ 0x0/0) in DBI 1.634-ithread (pid 5792)
    -> prepare for DBD::ODBC::db (DBI::db=HASH(0x35c54c8)~0x35c5420 'SELECT
        P.PersonLoginID
FROM
        Personnel.Persons AS P
        INNER JOIN Personnel.Memberships AS M ON M.PersonId = P.PersonId
        INNER JOIN Personnel.Groups AS G ON G.GroupId = M.GroupId
WHERE
    UPPER(P.PersonLoginID) = UPPER('?')
        AND (G.GroupAbbv = 'MyGroup'
                OR G.GroupAbbv = 'SubGroup1'
                OR G.GroupAbbv = 'SubGroup2')
        AND (M.StartDate <= '?'
                OR M.StartDate BETWEEN '?' AND '?')
        AND (M.EndDate >= '?'
                OR M.EndDate IS NULL)
') thr#299a010
    <- prepare= ( DBI::st=HASH(0x3641e08) ) [1 items] at billing.cgi line 353
SomeLoginID
2016-03-10 13:54:44
2016-03-10 16:11:05
    -> bind_param for DBD::ODBC::st (DBI::st=HASH(0x3641e08)~0x3641d78 1 'SomeLoginID' 12) thr#299a010
    -> DESTROY for DBD::ODBC::st (DBI::st=HASH(0x3641d78)~INNER) thr#299a010
    <- DESTROY= ( undef ) [1 items] at billing.cgi line 361

诊断打印显示应该进入查询的值。

357:      print STDERR "$PersonLoginID\n";  --> SomeLoginID
358:      print STDERR "$start\n";          --> 2016-03-10 13:54:44
359:      print STDERR "$end\n";            --> 2016-03-10 16:11:05

我在过去一个小时左右读过的一些 DBI 文档说 ? 是唯一的 "portable" 占位符。 MS SQL 更喜欢其中之一吗?

我见过一些示例,其中字符串的占位符不在占位符字符周围使用单引号,但这对我不起作用。

想法?

不要引用占位符,即使是 char/string 类型。

...
WHERE
     UPPER(P.PersonLoginID) = UPPER('?')
...

应该只是

...
WHERE
     UPPER(P.PersonLoginID) = UPPER(?)
...