從資料庫取得特定時間以前到現在的資料,並寄出信件

如題,目的是為了從資料庫取得特定時間以前到現在的資料,並寄出信件

實際需求為:

1.先從db抓取特定時間以前的資料
2.將取得的資料用html格式寄出信件

目前想法:
1. 從db抓取特定時間以前的資料,逐筆寫入html
2. 從db抓取不限制時間,但是符合其他搜尋條件的資料,透過for迴圈去比對每一筆資料的時間欄位是否符合特定時間到現在時間的這個區間

SQL語法:BETWEEN

以下轉自亂馬客提供的範例有提到比對時間的部分,但是在ORACLE平台不可行:

BETWEEN ... AND 會選取介於2個值之間的資料。

--***************************************************** --找出 出版日期為2011/10/10~2011/12/10的書 (date) SELECT * FROM @BOOKLIST WHERE PUBLISH_DATE BETWEEN '2011/10/10' AND '2011/12/10' ORDER BY PUBLISH_DATE --出版日期為2011/12/10 10:10, 2011/12/10 20:30沒有被找出來 --找出 出版日期為2011/10/10 00:00:00 ~ 2011/12/10 23:59:59 的書 (date) SELECT * FROM @BOOKLIST WHERE PUBLISH_DATE BETWEEN '2011/10/10 00:00:00' AND '2011/12/10 23:59:59' ORDER BY PUBLISH_DATE

ORACLE平台比對時間的方法,以下轉自獅子內心的OS提供的筆記(鞠躬):
Oracle Between用法-迄日要包含時分秒-加映改善效能
若未加時分秒,會導致日期欄位若有記錄時分秒,該筆資料正好位於迄日時,會漏掉!


範例如下:
序號    日期區間
------    --------------------------
1000    2010/1/30
2000    2010/1/30
3000    2010/1/30 上午 12:00:58
4000    2010/1/30 下午 09:11:57
5000    2010/1/31
6000    2010/1/31 上午 12:01:12
7000    2010/1/31 下午 04:58:25
1.最後兩筆 (6000、7000) 會漏掉的寫法
SELECT CT.SEQ, CT.EFF_DATE FROM CT WHERE CT.EFF_DATE BETWEEN TO_DATE('2010/01/30', 'YYYY/MM/DD') AND TO_DATE('2010/01/31', 'YYYY/MM/DD');

2.正確寫法:
SELECT CT.SEQ, CT.EFF_DATE FROM CT WHERE CT.EFF_DATE BETWEEN TO_DATE('2010/01/30', 'YYYY/MM/DD') AND TO_DATE('2010/01/31 23:59:59', 'YYYY/MM/DD HH24:MI:SS');


需要注意的效能問題

因為使用了 Between 和 To_Date 函式,造成用不到 Index Key,效能頗差,可利用 Function-base index 解決。
官方參考資料:Creating a Function-Based Index

上述 Sql 要做效能調整,可以建立以下 Index:

CREATE INDEX IDX_EFF_DATE ON CT 
(TO_CHAR(EFF_DATE, 'YYYYMMDDHH24MISS'));
然後查詢的 Sql 改成:

SELECT CT.SEQ, CT.EFF_DATE FROM CT
 WHERE TO_CHAR(CT.EFF_DATE, 'YYYYMMDDHH24MISS') 
 BETWEEN '20100130000000' AND '20100131235959';

就會用到 Index,筆數多時,效能差可大了~~
以上皆轉自獅子內心的OS(再次感謝)

PS.我自己測試的語法:
select * from TABLE_NAME_201705 
where COLUMN_NAME IN ('KRE' ,'KR3') 
AND MODIFY_DATE BETWEEN TO_DATE('2011/10/10 00:00:00','YYYY/MM/DD HH24:MI:SS') AND TO_DATE('2020/12/10 23:59:59','YYYY/MM/DD HH24:MI:SS');


寄信的部分是透過php mail()函式進行

目前遇到需要注意的地方有:
1. 使用附加檔時的程式處理

//附加檔案處理程序

$file_name = $key_date.'_監控通知('.$ten_name.' '.$data7.').docx';
$content_type = 'application/vnd.ms-word';
$data = chunk_split(base64_encode(file_read($docx_save_file)),76,"\n");
$mail_content  = $content;
//$mail_content .= "Content-Type: $content_type; name=$file_name\n";
//$mail_content .= "Content-Disposition: attachment; filename=$file_name\n";
$mail_content .= "Content-Transfer-Encoding: base64\n\n";
//$mail_content .= "$data\n";
$mail_content .= "--$mime_boundary--\n";

紅色部分為不可刪除的部分,若是刪除,會造成信件內容出現亂碼,或是程式卡在送信端。

2. 轉成html格式有兩種方式

(a).使用php的長字串:
$long_string <<< MESSAGE
以下皆為需要用到的字串
字串
字串
字串
字串
字串
字串
字串
字串
字串
字串
字串
字串
MESSAGE;

(b). 先寫好要顯示的html頁面的所有內容,包含所有tags都要包在php字串的'符號內,是php常見的字串標示法。

目前程式測試出來的顯示記錄
start run time(sendmailtest_ya.php) : 2017-10-25 19:01:35
==sql==
SELECT * FROM APP_FP_NOTIFY_201710
WHERE MMK_ID IN ('KRE' ,'KR3')
AND MODIFY_DATE BETWEEN TO_DATE('1970-01-01 06:03:37,'YYYY/MM/DD HH24:MI:SS')
AND TO_DATE('2017-10-25 19:01:35','YYYY/MM/DD HH24:MI:SS')
AND SEND_FLAG ='N' ORDER BY MODIFY_DATE DESC
已取得異常資料
mail successed!total count : 1 end run time(sendmailtest_ya.php) : 2017-10-25 19:02:11

現在運行狀況
mail()寄出信件後,在outlook收到的信件,就算不加入附加檔案處理,仍會含有空白的*.txt -->ATT00001.txt (226B)

根據[An extra attachement is being sent in php]解析

// email fields: to, from, subject, and so on 
$to = "you@home.com"; 
$from = "me@home.com";  
$subject ="Test mail";  
$message = "please check the csv out!"; 
$headers = "From: $from"; 

$fileName = pathtocsv;

// boundary  
$semi_rand = md5(time());  
$mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";  

// headers for attachment  
$headers .= "\nMIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"{$mime_boundary}\"";  

// multipart boundary  
$message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";  
$message .= "--{$mime_boundary}\n"; 

// preparing attachments 
$file = fopen($fileName,"rb"); 
$data = fread($file,filesize($fileName)); 
fclose($file); 
$data = chunk_split(base64_encode($data)); 
$message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"record.csv\"\n" .  
"Content-Disposition: attachment;\n" . " filename=\"test.csv\"\n" .  
"Content-Transfer-Encoding: base64\n\n" . $data . "\n\n"; 
$message .= "--{$mime_boundary}\n"; 

mail($to, $subject, $message, $headers);

可行方法是把原有程式的 $message .= "--{$mime_boundary}\n"; 改成  $message .= "--{$mime_boundary}--\n";,主要就是在}後方補上--即可。

以下截取自[drew010]的回覆(Tks!)

RFC 2046 ( § 5.1.1 - Common Syntax [page 19]) states that:
The boundary delimiter line following the last body part is a
distinguished delimiter that indicates that no further body parts
will follow. Such a delimiter line is identical to the previous
delimiter lines, with the addition of two more hyphens after the
boundary parameter value.
--gc0pJq0M:08jU534c0p--
Since the last boundary was missing, it seems to be the default behaviour that Outlook creates an attachment containing some extra data or an empty attachment.
The second answer here by James-Luo may also be valid. He states that adding an attachment to a MIME message prior to the message body can result in similar outcome with the attachments.

以及討論串:

Here's the MS KB artice on it - support.microsoft.com/default.aspx?scid=kb;en-us;969854 (but I couldn't see the errors)


mail()參考程式碼

<?php
// Multiple recipients
$to = 'johny@example.com, sally@example.com'; // note the comma

// Subject
$subject = 'Birthday Reminders for August';

// Message
$message = '
<html>
<head>
<title>Birthday Reminders for August</title>
</head>
<body>
<p>Here are the birthdays upcoming in August!</p>
<table>
<tr>
<th>Person</th><th>Day</th><th>Month</th><th>Year</th>
</tr>
<tr>
<td>Johny</td><td>10th</td><td>August</td><td>1970</td>
</tr>
<tr>
<td>Sally</td><td>17th</td><td>August</td><td>1973</td>
</tr>
</table>
</body>
</html>
';

// To send HTML mail, the Content-type header must be set
$headers[] = 'MIME-Version: 1.0';
$headers[] = 'Content-type: text/html; charset=iso-8859-1';

// Additional headers
$headers[] = 'To: Mary <mary@example.com>, Kelly <kelly@example.com>';
$headers[] = 'From: Birthday Reminder <birthday@example.com>';
$headers[] = 'Cc: birthdayarchive@example.com';
$headers[] = 'Bcc: birthdaycheck@example.com';

// Mail it
mail($to, $subject, $message, implode("\r\n", $headers));
?>


留言

熱門文章