dqtu14636 2012-09-06 21:27
浏览 31
已采纳

使用文件Mtime(PHP)时,为什么插入SQL Server会失败,而使用Ctime时则不然?

I am attempting to walk a directory (using PHP) and get the modified and created time of the files, updating or inserting as needed to an SQL Server 2003 table.

I am using PHP's DirectoryIterator in order to do this, and it works flawlessly if I only use the object's getCTime() function. If I move to include or instead use the objects getMTime() method, SQL Server throws out an error at me on insert/update:

22003 : [Microsoft][SQL Server Native Client 10.0][SQL Server]Arithmetic overflow error converting expression to data type smalldatetime.

This error ONLY occurs when using the object getMTime() method. Testdir has two files in it, solely for testing obviously.

I have searched for help with this via Google, and especially on Stackoverflow (One, Two, Three). Those StackOverflow questions are for a SELECT statement however, and say to use CONVERT function of SQL. The only semi-relevant item I have found was a blog post which says to ensure the SQL user has the default language set appropriately. In my user case, it is set properly to 'English'.

Here is the entire function and subsequent call:

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>";

When this code is run with mtime as the $file_time (through web browser) I get the following output:

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.

If I change out $file_time to use getCTime() instead, the output completes with no errors:

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
        )

)

Even if that method specified in the StackOverflow question (linked above) work to have both cases of mtime and ctime upload properly, my question is still Why does using ctime work without any modification but mtime does not?

  • 写回答

1条回答 默认 最新

  • dongpingwu8378 2012-09-07 00:57
    关注

    Because SQL Server wants YYYY-MM-DD and in your case, your are sending YYYY-DD-MM. mdate gives you 2011-25-07, which isn't a valid date for YYYY-MM-DD, as 25 is not a valid month. It's just by chance that cdate is working because it's returning 2012-06-09 and 06 is a valid month. You either need to change your formatting or change the date localization on the server.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)
  • ¥20 matlab yalmip kkt 双层优化问题