Как связать параметр TS86 DATETIME ISO8601 с PDO?

Похоже, что PDO имеет проблемы с ISO 8601 отформатированные метки времени.

Я подключаюсь из 64-битной Ubuntu 16.04 под управлением PHP 7.0.8, используя Драйвер ODBC для Microsoft® 13 (предварительный просмотр) для 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 Driver 13 для SQL Server] Недопустимое символьное значение для спецификации приведения (SQLExecute [0] в /build/php7.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);

Но я пишу сценарий, который запускается каждую ночь примерно на 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);

5

Решение

Вам нужно будет использовать встроенный в SQL Server convert() функцию и укажите формат (126) который вы ему даете:

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

В документации упоминается :mmm в конце вашей строки, так что вам может понадобиться добавить вручную :000 в конце вашей строки даты, чтобы это работало.

1

Другие решения

После полдня, потраченного на решение той же проблемы, я бросил odbc и использовал вместо него dblib. Я установил пакет php7.0-sybase, адаптировал имя источника данных для моего соединения PDO и решил раз и навсегда.
Теперь каждая связка работает.

1

По вопросам рекламы [email protected]