2019年1月29日 星期二

php 的日期比較

在比對之前,先說明一下如何得到目前日期 在 php 5.2(含) 前可以用 date('Y-m-d') 在 php 5.2(不含) 後可以用 new DateTime() 雖然函數有一點點不同,但都需要注意時區可能產生的問題

接下來開始比較日期
使用函數 strtotime
  1. $Date1 = date('Y-m-d');
  2. $Date2 = '9999-12-31';
  3. if(strtotime($Date1) > strtotime($Date2)) {
  4. echo 'Date1 較新';
  5. }
  6. else {
  7. echo 'Date2 較新';
  8. }
基本上這樣就可以了,但是若是使用XAMPP,上面的語法可能會出現錯誤,原因在於 Y2K38漏洞,也被稱為Unix Millennium Bug,也就是 strtotime 只認得 2038-1-19 03:14:07 之前的日期時間,在此日期時間後的就會溢位,進而產生錯誤。

所以將語法修改如下,順便用了 php 5.2 版之後的語法
  1. $Date1 = date_format(new DateTime(),'U');
  2. // $Date2 = date_format(new DateTime('9999-12-31'),'U');
  3. // 這邊需要注意因為 DateTime()會包含時間的部分,所以在比較時要同時加上時間的部分(或去除時間的部分)來比較會較正確,
  4. // 或是將 $Date2 多加一天後再比較也行,所以將 $Date2 修改一下
  5. $Date2 = date_format(date_modify(new DateTime('9999-12-31'),'+1 days'),'U');
  6. if($Date1 > $Date2) {
  7. echo 'Date1 較新';
  8. }
  9. else {
  10. echo 'Date2 較新';
  11. }
參考資料/來源: 藍色小舖 php 討論區- 日期的比較 PHP轉換超過2038年的日期出錯問題解決

用Temp Table取代Cursor

cursor通常用來逐筆處理資料使用,下面是一個簡單的範例(MS SQL Server 2008)
  1. declare @myId int
  2. declare @myName nvarchar(20)
  3. declare @myCursor CURSOR
  4.  
  5. set @myCursor = CURSOR FAST_FORWARD
  6. FOR
  7. SELECT ID, NAME FROM Employee
  8. open @myCursor
  9. INTO @myId, @myName
  10. WHILE @@FETCH_STATUS = 0
  11. BEGIN
  12.  
  13. --DO SOMETHING
  14.  
  15. FETCH NEXT FROM @myCursor
  16. INTO @myId, @myName
  17.  
  18. END
  19.  
  20. CLOSE @myCursor
  21. DEALLOCATE @myCursor
用temp table來模擬cursor的操作模式,簡單的說就是把SELECT ID, NAME FROM Employee的結果存到temp table中,在逐步讀取,所以必須先建立一個temp table如下
  1. create table #tempEmployee
  2. (
  3. ID int,
  4. NAME nvarchar(20)
  5. )
然後把資料insert into select 到 #tempEmployee
  1. insert into #tempEmployee (ID,NAME)
  2. select ID,NAME
  3. from Employee
接下來,就是逐步讀取這個temp table #tempEmployee
在MS SQL Server中使用SET ROWCOUNT 1來控制select時一次只撈出一筆資料,而且每做完一筆就刪掉,直到#tempEmployee沒有資料為止
  1. declare @countTemp int --用來計算#tempEmployee還剩幾筆資料
  2.  
  3. --計算#tempEmployee資料數
  4. select @countTemp = count(*) from #tempEmployee
  5.  
  6. while(@countTemp > 0)
  7. begin
  8. set rowcount 1
  9. select @myId = ID, @myName = NAME from #tempEmployee
  10. --To Something
  11. --因為set rowcount 1的關係,所以一次只會刪一筆
  12. delete from #tempEmployee
  13.  
  14. --計算還剩幾筆,@countTemp > 0繼續
  15. select @countTemp = count(*) from #tempEmployee
  16. end
  17.  
  18. --#刪除 tempEmployee
  19. drop table #tempEmployee
  20.  
  21. --把select的預設比數恢復正常
  22. set rowcount 0
如此一般,完整的程式碼如下
  1. declare @myId int
  2. declare @myName nvarchar(20)
  3.  
  4. create table #tempEmployee
  5. (
  6. ID int,
  7. NAME nvarchar(20)
  8. )
  9.  
  10. declare @countTemp int --用來計算#tempEmployee還剩幾筆資料
  11.  
  12. --計算#tempEmployee資料數
  13. select @countTemp = count(*) from #tempEmployee
  14.  
  15. while(@countTemp > 0)
  16. begin
  17. set rowcount 1
  18. select @myId = ID, @myName = NAME from #tempEmployee
  19. --To Something
  20. --因為set rowcount 1的關係,所以一次只會刪一筆
  21. delete from #tempEmployee
  22.  
  23. --計算還剩幾筆,@countTemp > 0繼續
  24. select @countTemp = count(*) from #tempEmployee
  25. end
  26.  
  27. --#刪除 tempEmployee
  28. drop table #tempEmployee
參考資料/來源: 遜砲賴的爆肝筆記-stored procedure中不使用cursor逐步讀取資料列的方法