#php #sql-server #sqlsrv
#php #sql-сервер #sqlsrv
Вопрос:
Мы должны обновить нашу систему для использования PHP7.3 (перейти с MSSQL на драйвер базы данных SQLSRV и SQLSRV с PDO)
Моя проблема в том, что я не понимаю это поведение и как его правильно решить.
Когда я запрашиваю DateTime
столбец из базы данных, я получаю:
2019-03-26 00:00:00.000
Когда я пытаюсь сохранить одно и то же значение в DateTime
столбце базы данных, это не работает. Моя база данных принимает этот формат, например:
26-03-2019 00:00:00.000
по этой причине наш существующий уровень базы данных не работает должным образом.
мне нужна помощь, чтобы понять это поведение и как сообщить базе данных использовать один и тот же формат для запроса и ВСТАВКИ / ОБНОВЛЕНИЯ
В используемых нами запросах нет специальных преобразований, простой ВЫБОР / ОБНОВЛЕНИЕ / ВСТАВКА.
Версия PHP: PHP 7.3.3-1 ubuntu18.04.1 deb.sury.org 1 (cli) (собран: 7 марта 2019 20:31:49) (NTS )
Авторское право (c) 1997-2018 PHP Group Zend Engine v3.3.3, Авторское право (c) 1998-2018 Zend Technologies с Zend OPcache v7.3.3-1 ubuntu18.04.1 deb.sury.org 1, Авторское право (c) 1999-2018, автор Zend Technologies
SQLServer: MSSQL Server 2014
спасибо за любую подсказку
Комментарии:
1. пожалуйста, объясните, почему -1?
2. Ваш вопрос неясен. Формат неверен при выборе его ИЗ SQL или вставке в SQL?
Ответ №1:
1. Как получить значения даты и времени с SQL Server:
1.1. Извлеките значения даты и времени из пользовательского интерфейса SQL Server с PDO_SQLSRV-версией драйвера PHP для SQL Server:
При использовании драйвера PDO_SQLSRV значения из столбцов даты и времени возвращаются в виде строк до версии драйвера 5.6.0. В этом случае единственным вариантом является переформатирование значений даты и времени (например, с '2019-03-26 00:00:00.000'
на '26-03-2019 00:00:00.000'
). Начиная с версии 5.6.0, вы можете изменить это поведение с помощью атрибута PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE соединения или инструкции PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE и извлекать значения полей даты и времени в качестве переменной PHP DateTime. Затем вы можете легко отформатировать эту переменную как строку, используя DateTime::format.
<?php
// Connection
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
// Datetime values as PHP DateTime object
try {
$query = "SELECT GETDATE() AS DateTimeColumn";
$stmt = $conn->prepare($query);
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt->execute();
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row["DateTimeColumn"]->format('Y-m-d H:i:s.v') . "<br>";
}
$stmt = null;
// Datetime values as text
try {
$query = "SELECT GETDATE() AS DateTimeColumn";
$stmt = $conn->prepare($query);
$stmt->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, false);
$stmt->execute();
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
echo $row["DateTimeColumn"] . "<br>";
}
$stmt = null;
// End
$conn = null;
?>
1.2. Извлеките значения даты и времени выходных параметров из хранимой процедуры SQL Server, используя PDO_SQLSRV версию драйвера PHP для SQL Server:
Примечание из документации объясняет, что PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE
атрибут connection или statement применяется только к обычной выборке типов даты и времени, поскольку объекты DateTime не могут быть указаны в качестве выходных параметров. В этой ситуации единственным возможным вариантом является передача datetime
выходного параметра хранимой процедуры в виде строковой переменной PHP. Возвращаемое значение зависит от языковой среды для сеанса.
Хранимая процедура:
CREATE PROCEDURE spReturnDateTime
@datetime datetime OUTPUT
AS
BEGIN
SET NOCOUNT ON
SELECT GETDATE() AS [DateTime]
SET @datetime = GETDATE()
END
PHP:
<?php
// Connnection
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_SYSTEM);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
// Output parameters from stored procedure
try {
//
$sql = "
SET LANGUAGE 'English'
EXEC :errcode = spReturnDateTime @datetime = :datetime
";
$errcode = 0;
$datetime = "";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':errcode', $errcode, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(':datetime', $datetime, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 50);
$stmt->execute();
do {
while ($row = $stmt->fetch( PDO::FETCH_ASSOC) ){
echo $row["DateTime"]."<br>";
}
} while ($stmt->nextRowset());
$stmt = null;
echo $datetime."<br>";
//
$sql = "
SET LANGUAGE 'Bulgarian'
EXEC :errcode = spReturnDateTime @datetime = :datetime
";
$errcode = 0;
$datetime = "";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':errcode', $errcode, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(':datetime', $datetime, PDO::PARAM_STR | PDO::PARAM_INPUT_OUTPUT, 50);
$stmt->execute();
do {
while ($row = $stmt->fetch( PDO::FETCH_ASSOC) ){
echo $row["DateTime"]."<br>";
}
} while ($stmt->nextRowset());
$stmt = null;
echo $datetime."<br>";
} catch (PDOException $e) {
die ("Error executing query. ".$e->getMessage());
}
// End
$conn = null;
?>
Результаты:
2021-06-10 10:05:54.580
Jun 10 2021 10:05AM
2021-06-10 10:05:54.580
юни 10 2021 10:05AM
1.3. Извлеките значения даты и времени из SQL Server, используя SQLSRV-версию драйвера PHP для SQL Server:
По умолчанию типы smalldatetime
, datetime
date
, time
datetime2
, datetimeoffset
'ReturnDatesAsStrings'
,,, будут возвращены как объекты PHP DateTime, но это поведение может быть изменено путем установки,, опции в строке подключения или на уровне инструкции:
<?php
// Connection
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
$cinfo = array(
"Database" => $database,
"UID" => $username,
"PWD" => $password
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
// Datetime values as PHP DateTime object
$query = "SELECT GETDATE() AS DateTimeColumn";
$options = array('ReturnDatesAsStrings' => false);
$stmt = sqlsrv_query($conn, $query, null, $options);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
echo $row["DateTimeColumn"]->format('Y-m-d H:i:s.v') . "<br>";
}
sqlsrv_free_stmt($stmt);
// Datetime values as text
$query = "SELECT GETDATE() AS DateTimeColumn";
$options = array('ReturnDatesAsStrings' => true);
$stmt = sqlsrv_query($conn, $query, null, $options);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
echo $row["DateTimeColumn"] . "<br>";
}
sqlsrv_free_stmt($stmt);
// End
sqlsrv_close($conn);
?>
1.4. Извлекать значения даты и времени из расширения SQL Server uisng MSSQL PHP (расширение было удалено в PHP 7.0.0):
При использовании расширения MSSQL значения даты и времени возвращаются в виде текста, но формат зависит от mssql.datetimeconvert
настройки в php.ini
файле. Когда этот параметр установлен ON
, значения даты и времени преобразуются на основе настроек SQL Server, а когда установлен OFF
, значения даты и времени преобразуются в YYYY-MM-DD hh:mm:ss
формат.
<?php
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
$conn = mssql_connect($server);
if ($conn === false) {
echo "Error (mssql_connect): ".mssql_get_last_message();
exit;
}
mssql_select_db($database, $conn);
$query = "SELECT DateTimeColumn FROM OneTable";
$stmt = mssql_query($sql, $conn);
if ($stmt === false) {
echo "Error (mssql_query): ".mssql_get_last_message();
exit;
}
while ($row = mssql_fetch_assoc($stmt)) {
echo print_r($row, true);
}
mssql_free_result($stmt);
mssql_close($conn);
?>
В качестве дополнительного примечания, похоже, что этот параметр находится ON
в вашей серверной среде, потому что вы можете отправлять подобные даты '26-03-2019 00:00:00.000'
без ошибок.
2. Как передать значения даты и времени на SQL Server:
Как правило, значения даты и времени могут быть переданы SQL Server с использованием однозначного формата datetime ( yyyymmdd
или yyyy-mm-ddThh:mm:ss
) и параметризованного оператора.
2.1. Передать значения даты и времени в пользовательский интерфейс SQL Server с PDO_SQLSRV-версией драйвера PHP для SQL Server:
<?php
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
try {
$conn = new PDO("sqlsrv:server = $server; Database = $database", $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
try {
$query = "INSERT INTO OneTable (DateTimeColumn) VALUES (?)";
$datetime = (new DateTime())->format("Y-m-dTH:i:s");
$stmt = $conn->prepare($query);
$stmt->bindParam(1, $datetime);
$stmt->execute();
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
$stmt = null;
$conn = null;
?>
2.2. Передавать значения даты и времени в SQL Server, используя SQLSRV-версию драйвера PHP для SQL Server:
В этой версии драйвера вы можете использовать синтаксис расширенных параметров и передавать значение datetime как объект PHP DateTime с информацией о типах данных параметра PHP и SQL Server.
<?php
$server = "serverinstanse";
$database = "database";
$username = "username";
$password = "password";
$cinfo = array(
"Database" => $database,
"UID" => $username,
"PWD" => $password
);
$conn = sqlsrv_connect($server, $cinfo);
if ($conn === false) {
echo "Error (sqlsrv_connect): ".print_r(sqlsrv_errors(), true);
exit;
}
$query = "INSERT INTO OneTable (DateTimeColumn) VALUES (?)";
$datetime = new DateTime();
$params = array(
array($datetime, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_DATETIME, SQLSRV_SQLTYPE_DATETIME)
);
// or as usual, pass datetime values as text
//$params = array($datetime->format("Y-m-dTH:i:s"));
$stmt = sqlsrv_query($conn, $query, $params);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
?>