我正在尝试遍历目录(使用 PHP)并获取文件的修改和创建时间,根据需要更新或插入 SQL Server 2003 表。
我正在使用 PHPDirectoryIterator
来做到这一点,如果我只使用对象的getCTime()
函数,它就可以完美地工作。如果我移动到包含或改为使用 objectsgetMTime()
方法,SQL Server 在插入/更新时会向我抛出一个错误:
22003:[Microsoft][SQL Server Native Client 10.0][SQL Server]将表达式转换为数据类型 smalldatetime 时出现算术溢出错误。
此错误仅在使用对象getMTime()
方法时发生。Testdir 里面有两个文件,显然只是为了测试。
我已经通过谷歌搜索了这方面的帮助,尤其是在 Stackoverflow(一、二、三)上。然而,那些 StackOverflow 问题是针对一个SELECT
语句的,并且说是使用CONVERT
SQL 的函数。我发现的唯一半相关的项目是一篇博客文章,它说要确保 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
?