在使用PHP+mysql開發的時候,插入/刪除數據是免不了的,我想大家早已習慣了諸如bbs發表,留言簿的一條,一條的數據輸入的模式. 但是在很多工程裡,逐條輸入數據是不被允許的. 比如,輸入學生的考試成績,逐條輸入需要點擊"提交"40多次,這很大程度消磨了班主任的耐心和時間,如何"一口氣"輸入完一個班級的數據,是校園管理系統的一個要點(當然,其他場合也經常有這種要求) 下面的文章僅僅是我的工作經驗,供學習PHP的同道們參考.(高手大概會一笑了之吧)
主要思路有二: 1.動態生成表單和域的屬性 2.用變量表示變量 首先看看數據結構: create table score ( score_id int unsigned primary key auto_increment, s_no int unsigned not null, grade tinyint not null, class tinyint not null, class2 tinyint , subject char(6) not null, score tinyint default '0' )type=MYISAM; create table students ( imitate int unsigned primary key, s_no int unsigned , s_name char(10) not null, ...... )type=MYISAM; 其中s_no是學號,是整個程序的關鍵.由於這個學校語數外是分8個等級班的,所以,成績表中多一個class2字段. 目的是在一個表單中輸入全班40多人的"分類班,成績"數據,一次性提交. 由於輸入牽涉多個字段,而且需要插入的記錄不止一條,給編程提高了難度.這裡牽涉了2個字段,但是我們舉一反三後可以解決任何多個字段的問題.(當然,表單是需要動態生成的.)
廢話不多說了,看看源代碼吧: (因為這個站點沒有把Html標簽給過濾掉,請大家把下面代碼copy到dreamweaver的代碼視圖裡再看.) <html> <? //連接數據庫 include("const.php"); include("link.php"); //如果沒有表單提交,執行下面操作 if(!empty($HTTP_POST_VARS)) { //獲得POST變量 $grade = $_POST["grade"]; $tclass = $_POST["tclass"]; //由於學號最後兩位不會超過60,我們一個一個接收 for($i = 1;$i < 60;$i++) { //第一條記錄的分類班和成績的"變量名"(注意還不是數值) $fenlei = "a".$i; $score = "b".$i; //因為學號可能有間隔,先判斷值是否存在 if(!empty($_POST["$fenlei"]) && !empty($_POST["$score"])) { //如果register_globals = on,則下面直接使用$$fenlei和$$score. //我們假設register_globals = on,如果你的設置不是,那麼請再定義兩個變量接收它們的值. //重新生成完整的學號. $s_no = $grade*10000+$class*100+$i; //生成query語句,用到了"變量的變量".當然,如果register_globals = off,則又有不同. $query = "insert into score (s_no,grade,class,class2,score) values ('$s_no','$grade','$tclass','".$$fenlei."','".$$score."')"; //顯示,看看語句是否正確. echo $query."<br>"; //執行語句,我沒有寫出來. } } } ?> <head> <title>TEST</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> </head> <body> <form action="test.php" method="post" name="form1" target="_self"> <table width="400" border="0" cellpadding="0" cellspacing="0"> <tr> <td height="20" colspan="3">年級(入學年): <input name="grade" type="text" id="grade" size="10" maxlength="2"> 班級: <input name="tclass" type="text" id="tclass" size="10" maxlength="2"></td> </tr> <tr> <td width="200" height="20">學號</td> <td width="100">分類班</td> <td width="100">成績</td> </tr> <? //取得學生的學號.應該在此前獲得班級和年級,並寫進where子句的,但我們只是做個試驗,就省略了. $query = "select s_no from students where ......"; $re = mysql_query($query,$lnk); while($form = mysql_fetch_object($re)) { //獲得學號的最後兩位. $student_no = $form->s_no % 100; ?> <tr> <td height="20"> <?=$form->s_no;?> </td> <!- 動態生成text域的name屬性,注意!不要寫id屬性,以免重復! -> <td><input name="a<?=$student_no;?>" type="text" size="10" maxlength="10"></td> <td><input name="b<?=$student_no;?>" type="text" size="10" maxlength="10"></td> </tr> <? } ?> <tr> <td height="20" colspan="3"><div align="center"> <input type="submit" name="Submit" value="Submit"> </div></td> </tr> </table> </form> </body> </html>
結果如下,共有這麼些SQL語句被執行: insert into score (s_no,grade,class,class2,score) values ('990001','99','6','a','90') insert into score (s_no,grade,class,class2,score) values ('990002','99','6','a','86') insert into score (s_no,grade,class,class2,score) values ('990003','99','6','a','84') insert into score (s_no,grade,class,class2,score) values ('990005','99','6','b','75') insert into score (s_no,grade,class,class2,score) values ('990006','99','6','b','80') insert into score (s_no,grade,class,class2,score) values ('990007','99','6','b','79') 一個班級需要40多次循環,mysql_query()函數執行40余次,在網絡環境較好的情況下,耗時1秒左右(mysql就是快)當然,可以生成一條超長的SQL語句,執行一次query.至於哪個效率更高,大家自己試試看吧. 這個方法的優點就是可以不必一次次點擊"遞交",不足之處在於,一次必須把數據全部輸入!(有點矛盾?)是的!如果再次使用這個功能,而又輸入重復的數據會怎樣?解決辦法是有的,就是每次循環時執行query前,判斷該記錄是否存在.這似乎又得執行一條額外的query.就是說,要確保數據正確,而一個班有n個人的話,總共需要N*2次query. 還有一個辦法是在生成表單的時候加以限制,這樣可以分散系統負荷,明顯要好過前一個方案. 不知道還有沒有更好的辦法使效率和穩定兼得,靠大家指教了.