PHP sqlsrv驱动程序和PDO驱动程序之间的数据类型差异



这里我使用的是sqlsrv:

$conn = sqlsrv_connect("192.168.1.102,1433", array("Database"=>"RF_User", "UID"=>"rfo-gcp", "PWD" => ""));
$tsql = "SELECT birthdate FROM tbl_rfaccount WHERE id = ?";
$stmt = sqlsrv_query($conn, $tsql, array("test"));
$result = sqlsrv_fetch_array($stmt);
var_dump($result);

结果:array(2) { [0]=> object(DateTime)#1 (3) { ["date"]=> string(26) "2020-04-19 20:40:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } ["birthdate"]=> object(DateTime)#1 (3) { ["date"]=> string(26) "2020-04-19 20:40:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" } }

这里我使用的是PDO:

$conn = new PDO("sqlsrv:Server=192.168.1.102,1433; Database=RF_User;", "rfo-gcp", "");
$tsql = "SELECT birthdate FROM tbl_rfaccount WHERE id = cast(? as varchar(13))";     
$stmt = $conn->prepare($tsql);
$stmt->execute(array("test"));
$result = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($result);

结果:array(1) { ["birthdate"]=> string(19) "2020-04-19 20:40:00" }

如果您注意到,我不得不在PDO代码上使用cast(? as varchar(13))。没有它就不会返回任何行。在sqlsrv上,我不必使用CAST()函数。为什么会这样?此外,数据库上的id列是BINARY(13),那么为什么我必须将id强制转换为varchar而不是binary(使用二进制强制转换也找不到行(?

为什么日期和时间值的返回方式不同

事实上,这只是一个背景。

使用PDO_SQLSRV(如文档中所述(时,日期和时间类型(smalldatetime、datetime、date、time、datetime2和datetimeoffset(默认情况下以字符串形式返回。PDO::ATTR_STRINGIFY_FETCHES和PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE属性都没有任何效果。为了将日期和时间类型检索为PHP DateTime对象,请将连接或语句属性PDO::SQLSRV_ATTR_FETCHES_DateTime_TYPE设置为true(默认情况下为false(

当您使用SQLSRV驱动程序(同样来自文档(时,smalldatetime、datetime、date、time、datetime2和datetimeoffset类型将作为PHP datetime对象返回。可以通过在连接字符串或语句级别设置'ReturnDatesAsStrings'选项来更改此行为。

$conn = sqlsrv_connect(
"192.168.1.102,1433", 
array(
"ReturnDatesAsStrings"=>true,
"Database"=>"RF_User", 
"UID"=>"rfo-gcp", 
"PWD" => ""
)
);

请注意,其中一些功能取决于用于SQL Server的PHP驱动程序的版本。

如何转换参数值

在语句中使用CAST()CONVERT()函数并将参数值与字符串值绑定应该可以。当然,您可以在绑定参数时指定参数数据类型。

对于PDO_SQLSRV,您应该扩展PDOStatement::bindParam((的语法。

对于SQLSRV,当您调用sqlsrv_query()sqlsrv_execute()时,可以使用扩展的$params语法来指定SQL Server数据类型。

我能够重现这个问题(PHP 7.1.12,SQL Server 4.3.0+9904的PHP驱动程序,SQL Server 2012(,解决方案是使用:

$params = array($id, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_BINARY);          // SQLSRV
$stmt->bindParam(1, $id, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY); // PDO_SQLSRV 

表:

CREATE TABLE tbl_rfaccount (id binary(13), birthdate datetime)
INSERT INTO tbl_rfaccount (id, birthdate) VALUES (CONVERT(binary(13), 'Test'), GETDATE())

PHP:

<?php
...
// 
$id = "Test";
// SQLSRV
$tsql = "SELECT birthdate FROM tbl_rfaccount WHERE id = ?";
$params = array($id, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_BINARY);
$stmt = sqlsrv_query($conn, $tsql, $params);
if ($stmt === false) {
echo "Error (sqlsrv_query): ".print_r(sqlsrv_errors(), true);
exit;
}
$result = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
var_dump($result);
// PDO_SQLSRV
$tsql = "SELECT birthdate FROM tbl_rfaccount WHERE id = ?";     
$stmt = $conn->prepare($tsql);
$stmt->bindParam(1, $id, PDO::PARAM_LOB, null, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC);
var_dump($result);
...
?> 

最新更新