0

我正在尝试遍历目录(使用 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语句的,并且说是使用CONVERTSQL 的函数。我发现的唯一半相关的项目是一篇博客文章,它说要确保 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 问题(上面链接)中指定的方法可以同时正确上传mtimectime上传,我的问题仍然是为什么使用ctime没有任何修改但没有任何修改mtime

4

1 回答 1

2

因为 SQL Server 需要 YYYY-MM-DD,而在您的情况下,您发送的是 YYYY-DD-MM。mdate 为您提供 2011-25-07,这不是 YYYY-MM-DD 的有效日期,因为 25 不是有效月份。cdate 正在工作只是偶然,因为它返回 2012-06-09 并且 06 是有效月份。您需要更改格式或更改服务器上的日期本地化。

于 2012-09-07T00:57:24.477 回答