Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP sqlsrv驱动程序和PDO驱动程序之间的数据类型差异_Php_Sql Server_Pdo_Binary_Sqlsrv - Fatal编程技术网

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

PHP sqlsrv驱动程序和PDO驱动程序之间的数据类型差异,php,sql-server,pdo,binary,sqlsrv,Php,Sql Server,Pdo,Binary,Sqlsrv,这里我使用的是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")); $resu

这里我使用的是
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){“DateTime”=>string(26)“2020-04-19 20:40:00.000000”[“timezone"type”=>int(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
(使用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对象返回。可以通过在连接字符串或语句级别设置
“ReturnDateSasString”
选项来更改此行为

$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,您应该扩展其语法

对于SQLSRV,在调用
SQLSRV\u query()\SQLSRV\u 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:



您应该在绑定的数组中强制转换它,而不是强制转换占位符。@JayBlanchard怎么会这样?这是我理解的,但可能不是你的意思:
$stmt->execute(数组(“cast('test'为varchar(13))))
是一个占位符,而不是一个值,因此您将强制转换占位符是没有意义的。但是将该值转换为列类型(VARCHAR)根本没有意义,因为该值是数字、字符串或布尔值。在这种情况下,值
text
只是一个字符串。如果不执行此铸造,会出现什么错误?
id
的列类型是什么,
test
是否是该列和类型的适当值?@JayBlanchard该列类型是
BINARY(13)
(旧数据库,无法更改该值)。如果我不执行强制转换,就没有错误,它只是在应该的时候找不到记录。如果列类型是二进制的,那么为什么要尝试使用文本值从该列中选择?我想这就是断开连接的地方。我已经知道日期/时间值返回方式不同的原因,但感谢您澄清这一点。这里的问题是将值强制转换为正确的数据类型。虽然SQLSRV具有数据类型
SQLSRV\u SQLTYPE\u BINARY
,但PDO\u SQLSRV没有。我一直在使用PDO,我不知道如何才能做到这一点。@DanVeira我认为您应该使用正确的参数绑定。请参阅更新的答案。谢谢。哇@Zhorov!很好的解释!我很少再使用SQL server了,但这让我了解了在使用SQL server时遇到的一些问题。@Zhorov,这很有效!SQLSRV(没有PDO)似乎是数据类型方面的高级驱动程序。还有,你熟悉拉威尔吗?知道如何将这些驱动程序选项传递给它的查询生成器吗?谢谢大家!@丹维拉很高兴能帮忙!不,我没有拉威尔的经验。
<?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);

...
?>