Кажется, что PDO имеет проблемы с ISO 8601 отформатированными временными метками.
Я подключаюсь из 64-разрядного Ubuntu 16.04, работающего под управлением PHP 7.0.8, используя Microsoft® ODBC Driver 13 (Preview) для SQL Server®
Вот моя простая таблица:
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);
Неустранимая ошибка: Uncaught PDOException: SQLSTATE [22018]: Недопустимое значение символа для спецификации литья: 0 [Microsoft] [драйвер ODBC 13 для SQL Server] Недопустимое значение символа для спецификации литья (SQLExecute [0] at/build/php7. 0-lPMnpS/php7.0-7.0.8/внутр/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);
Но я пишу script, который работает в ночное время примерно на 2 миллиона записей, поэтому я бы действительно не переносил накладные расходы на запуск миллионов 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);