【问题标题】:Why does this insert to SQL Server fail when using file Mtime (PHP), but not when using Ctime?为什么在使用文件 Mtime (PHP) 时插入 SQL Server 会失败,但在使用 Ctime 时不会?
【发布时间】: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(OneTwoThree)寻求帮助。然而,这些 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 问题(上面链接)中指定的方法可以正确上传 mtimectime 两种情况,我的问题仍然是 为什么使用 ctime 无需任何修改但mtime 没有?

【问题讨论】:

    标签: php sql-server file-io windows-server-2003


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      • 2019-10-11
      • 2019-03-03
      • 2016-02-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多