【发布时间】:2012-08-31 18:42:54
【问题描述】:
我正在尝试遍历目录(使用 PHP)并获取文件的修改和创建时间,根据需要更新或插入 SQL Server 2003 表。
我正在使用 PHP 的 DirectoryIterator 来做到这一点,它完美地工作如果我只使用对象的 getCTime() 函数。如果我移动到包含或改为使用对象 getMTime() 方法,SQL Server 在插入/更新时向我抛出一个错误:
22003 : [Microsoft][SQL Server Native Client 10.0][SQL Server]将表达式转换为数据类型 smalldatetime 时出现算术溢出错误。
此错误仅在使用对象getMTime() 方法时发生。 Testdir 里面有两个文件,显然只是为了测试。
我已通过 Google,尤其是 Stackoverflow(One、Two、Three)寻求帮助。然而,这些 StackOverflow 问题是针对 SELECT 语句的,并说要使用 SQL 的 CONVERT 函数。我发现的唯一半相关项是a blog post,它表示要确保 SQL 用户正确设置了默认语言。在我的用户案例中,它被正确设置为“英语”。
这是整个函数和后续调用:
function fillArrayWithFileNodes( DirectoryIterator $dir )
{
$data = array();
require('connecttodbfile');
clearstatcache();
foreach ( $dir as $node )
{
if ( $node->isDir() && !$node->isDot() )
{
$data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
}
else if ( $node->isFile() )
{
$filename = $node->getFilename();
//Comment this out below and use CTime, Update works!
//$file_time = date('Y-d-m H:i:s', $node->getMTime());
//Comment this out and use MTime, Update DOES NOT WORK!
$file_time = date('Y-d-m H:i:s', $node->getCTime());
//Debug here, make sure I'm getting expected values
echo sprintf("Mtime (%s): %s - %s<br />Ctime (%s): %s - %s<br /> <br />", gettype($node->getMTime()), $node->getMTime(), gettype($node->getMTime()), date('Y-d-m H:i:s', $node->getMTime()), $node->getCTime(), date('Y-d-m H:i:s', $node->getCTime()));
$data[] = array('time'=>$file_time);
try {
$sQuery = <<<EOD
BEGIN TRAN
UPDATE files SET file_time=:ftime WHERE file_name=:fname
IF @@ROWCOUNT = 0 and @@ERROR = 0
BEGIN
INSERT INTO files (file_name,file_time) VALUES (:f_name, :f_time)
END
COMMIT TRAN
EOD;
$statm = $conn->prepare($sQuery);
//PDO doesn't like it if we name repeat variables the same. So even if you use the same variable more than once in your query, PDO says you need the exact number of variables in the execute array as is in your statement, all unique names.
$statm->execute(array(':ftime'=> $file_time, ':fname'=>$filename,':f_time'=> $file_time, ':f_name'=>$filename));
} catch(PDOException $err) {//SQL got mad at us. Figure out why.
echo $statm->errorCode() . " : ";
$error = $statm->errorInfo();
print_r( $error[2]);
exit(1);
}
}
}
return $data;
}
$fileData = fillArrayWithFileNodes( new DirectoryIterator( 'C:\testdir' ) );
echo "<pre>";
print_r($fileData);
echo "</pre>";
当此代码以mtime 作为$file_time 运行时(通过网络浏览器),我得到以下输出:
Mtime (integer): 1311599068 - 2011-25-07 08:04:28
Ctime (integer): 1346941012 - 2012-06-09 09:16:52
22003 : [Microsoft][SQL Server Native Client 10.0][SQL Server]Arithmetic overflow error converting expression to data type smalldatetime.
如果我将$file_time 改为使用getCTime(),则输出完成且没有错误:
Mtime (integer): 1311599068 - 2011-25-07 08:04:28
Ctime (integer): 1346941012 - 2012-06-09 09:16:52
Mtime (integer): 1265983000 - 2010-12-02 07:56:40
Ctime (integer): 1346941018 - 2012-06-09 09:16:58
Array (
[0] => Array
(
[time] => 2012-06-09 09:16:52
)
[1] => Array
(
[time] => 2012-06-09 09:16:58
)
)
即使 StackOverflow 问题(上面链接)中指定的方法可以正确上传 mtime 和 ctime 两种情况,我的问题仍然是 为什么使用 ctime 无需任何修改但mtime 没有?
【问题讨论】:
标签: php sql-server file-io windows-server-2003