如何将ISO8601 TSQL DATETIME参数与PDO绑定?

时间:2016-08-19 16:42:10

标签: php sql-server pdo odbc iso8601

PDO似乎存在ISO 8601格式化时间戳的问题。

我使用Microsoft® ODBC Driver 13 (Preview) for SQL Server®

从运行PHP 7.0.8的64位Ubuntu 16.04连接

这是我的简单表格:

CREATE TABLE dtest (
    "stamp" DATETIME
);

使用:

$pdoDB = new PDO('odbc:Driver=ODBC Driver 13 for SQL Server;
  Server='.DATABASE_SERVER.';
  Database='.DATABASE_NAME,
  DATABASE_USERNAME,
  DATABASE_PASSWORD
);
$pdoDB->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

$sql = "INSERT INTO dtest (stamp) VALUES ('2011-03-15T10:23:01')";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);

不起作用:

$sql = "INSERT INTO dtest (stamp) VALUES (?)";
$stmt = $pdoDB->prepare($sql);
$params = ['2011-03-15T10:23:01'];
$stmt->execute($params);
  

致命错误:未捕获PDOException:SQLSTATE [22018]:强制转换规范的字符值无效:0 [Microsoft] [SQL Server的ODBC驱动程序13]转换规范的字符值无效(/ build / php7中的SQLExecute [0]。 0-lPMnpS / php7.0-7.0.8 / EXT / PDO_ODBC / odbc_stmt.c:260)

如果我删除了T,那么

可行,以便'2011-03-15T10:23:01'成为'2011-03-15 10:23:01'

$sql = "INSERT INTO dtest (stamp) VALUES (?)";
$stmt = $pdoDB->prepare($sql);
$params = ['2011-03-15 10:23:01'];
$stmt->execute($params);

但是我正在编写一个每晚运行大约200万条记录的脚本,所以我真的而不是承担运行数百万str_replace('T', ' ', $param)

的开销。

我也尝试使用bindParam,但是它提供了相同的错误

$sql  = "INSERT INTO dtest (stamp) VALUES (:tdate)";
$stmt = $pdoDB->prepare($sql);
$date = '2011-03-15T10:23:01';
$stmt->bindParam(':tdate',$date,PDO::PARAM_STR);
$stmt->execute();

无论如何都要按原样绑定并执行此参数?我对错误消息有点怀疑,因为它似乎来自SQL Server,好像PDO完成了它的工作,但这没有意义,因为它能够处理没有参数化的类型转换

我也尝试过SQL转换:

使用:

$sql = "INSERT INTO dtest (stamp) VALUES (CONVERT(DATETIME, '2011-03-15T10:23:02', 126))";
$stmt = $pdoDB->prepare($sql);
$params = [];
$stmt->execute($params);

不起作用:

$sql = "INSERT INTO dtest (stamp) VALUES (CONVERT(DATETIME, ?, 126))";
$stmt = $pdoDB->prepare($sql);
$params = ['2011-03-15T10:23:02'];
$stmt->execute($params);

2 个答案:

答案 0 :(得分:1)

您需要使用SQL Server的内置convert()功能,并指定您提供的格式( 126 ):

$sql = "INSERT INTO dtest (stamp) VALUES (CONVERT(DATETIME, '2011-03-15T10:23:01', 126))";

文档在字符串末尾提到:mmm,因此您可能需要在日期字符串末尾手动添加:000才能生效。

答案 1 :(得分:1)

在尝试解决同一问题半天后,我最终放弃了odbc并使用了dblib。我安装了php7.0-sybase软件包,修改了我的PDO连接的数据源名称并解决了一次。 现在每个绑定都在工作。