標簽歸檔:access

PHP連接Access的方法

最近準備放棄使用許久的vbscript作為處理工作方面問題,而轉向PHP。
應該是ASP轉向PHP把,怎么是vbscript轉向php?這個我要說一下,處理工作方面問題,比如通過API導個數據…用ASP,PHP在IIS中執行肯定不行,寫個VBScript腳本,cscript 腳本名 讓他執行吧,別的不用關了。所以用腳本處理些數據轉換、導入導出還是不錯的選擇。
VBScript的致命的缺點是不支持引用文件,對HTTP請求方便不是很強,正則、XML處理起來不方面,JSON作為數據載體時就等著傻眼把。這是后用php作為腳本也是一個不錯的選擇。扯得有點遠了,換成了php,數據庫還是Access怎么辦?這個簡單,直接用com創建adodb實例即可。
現在已經創建好了數據庫,只填寫了部分域名,要通過php到域名查詢接口返回whois信息,并存到Access數據庫中,Access字段名已對應返回數組中的索引相同。

<?php
	set_time_limit(0);

	#因為要鏈接web,使用我前幾天寫的myhttp類。
	include('myhttp.clsss.php');
	#API操作,這里直接忽略,里邊有個get_domain_info來獲取API返回的數據,并處理成數組。
	include('api.function.php');
	
	$conn = new COM("Adodb.Connection");
	$conn -> open("provider=microsoft.jet.oledb.4.0;data source=D:\myweb\miaoqiyuan.cn\test\php-linkdb\domain.mdb");
	
	$dlist = new COM("ADODB.Recordset");
	$rs = new COM("ADODB.Recordset");
	
	$dlist -> open("select [domain],[did] from [domain] where isupdate=0",$conn,1,1);
	while(!$dlist -> eof()){
		echo "下載域名數據[".$dlist['domain']."].\n";
		$d=get_domain_info($dlist['domain']);
		$rs -> open("select * from [domain] where  did=".$dlist['did'],$conn,3,2);
		foreach($rs -> fields as $k => $v){
			if($k >= 6){
				$myvalue = $d[$rs[$k] -> name];
				if(isset($myvalue) && !is_array($myvalue)){
					$rs[$k] -> value = mb_convert_encoding($myvalue,"GB2312","UTF-8");
				}
			}
		}
		$rs['isupdate'] -> value = 2;
		$rs -> update();
		$rs -> close();
		$dlist -> movenext();
	}
?>

Access隨機讀取幾條記錄的方法

在程序設計時,可能經常用到隨機讀取幾條記錄的功能,MSSQL有order by NewID()的方法,Access怎么辦呢?
經過一翻百度搜索,還真找到了一些解決方案:

網上還有一種說法,有人采用一條SQL語句解決Access隨機讀取幾條記錄的問題:select top 50 * from table order by int(rnd()*50),不過這種方法我不敢茍同,也許是我的只是不夠淵博,我竟然不能理解。如果int(rnd()*50)應該是一個數了吧,int(rnd()*50),不初始化種子,所以每次返回結果都是一樣的,所以相當于沒有排序。

還有一種方法,就是先獲取總記錄數,然后取1~總數之間的隨機數,rs.move,不過這種方法有點羅嗦,在此不推薦。

再反回來看第一種方法,如果稍微修改一下,給rnd添加一個種子呢,比如第一條記錄rnd(1),第二條記錄rnd(2)….。有了,數據庫中的id字段(自動編號主鍵)不正是現成的嗎?select top 10 * from news order by rnd(id)。對就是這樣簡單。

在測試的時候還發現了另一個有趣的事情,如果order by 常量數字,比如select top 10 * from news order by 1 desc則是按第一列結果倒序來排序。

set rs=conn.execute,set rs=server.createobject(“ADODB.recordset”)的若干謊言

經常用asp的同行,可能會建議用set rs=conn.execute(sql)來代替set rs=server.createobject(“ADODB.recordset”):rs.open conn,sql,1,1。還有一些同行更提出了用set rs=conn.execute(sql):res=rs.getRows(100)來優化ASP程序。其實在沒有做此實驗前,我也是很相信這種方法的。實際效果果真如此嗎?經過一番測試,我發現結果遠非如此,set rs=server.createobject(“ADODB.recordset”)的方法比set rs=conn.execute的方法快4~5倍。這個結果您信嗎?不信,更我來一起做這個測試。貓七(苗啟源)博客首發,轉載請注明出處,原文地址: (http://www.okfdzs1868.com/p/conn-execute_rs-getrows)。

數據說明真相。首先創建一個多記錄的數據庫。

set conn=createobject("adodb.connection")
conn.open "provider=microsoft.jet.oledb.4.0;data source=E:\labs\miaoqiyuan.cn\g.mdb"
do while conn.execute("select count(id) from site")(0)<1000000
	conn.execute("insert into site(sitename,siteadmin,siteurl,sitekey) values('苗啟源','http://localhost/app_login/','http://www.okfdzs1868.com','e10adc3949ba59abbe56e057f20f883e')")
loop

經過幾個小時的運行,我得到了一個有63萬多條記錄的數據庫。數據庫大小為99.7MB(測試數據庫下載地址http://www.okfdzs1868.com/products/rs-execute-test.rar)。

為了保證數據的真實性,我們用公共的頭部header.asp來保存數據庫連接字符串。footer.asp來保存運行時間。

運行環境,Windows 2003 Server SP2。IIS6.0,CPU E2200 2.2GHz,內存2Gx2。硬盤300G SATA+80G ATA。

公共頭部:header.asp

< %
startTme=timer()
set conn=server.createobject("ADODB.connection")
conn.open "provider=microsoft.jet.oledb.4.0;data source="&server.mappath("g.mdb")
%>

公共底部:footer.asp

<hr />總共用時:< %=(timer()-startTme)*1000%>毫秒

測試方法:以三種方式,每頁100條記錄。同時讀取第6000頁到6099頁的記錄共一萬條,并測出運行時間。

test1.asp,采用set rs=server.createobject(“ADODB.recordset”)的方法。


< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",conn,1,1
	rs.pagesize=100
	rs.absolutepage=6000+k
	i=0
	do while not rs.eof and i<100
		i=i+1
		response.write rs("id")&":"&rs("sitename")&"<br />"&vbCrlf
		rs.movenext
	loop
	rs.close
	set rs=nothing

next
%>

test2.asp 采用set rs=conn.execute()的方法


< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=conn.execute("select * from site")
	rs.movefirst
	rs.move (6000+k)*100
	i=0
	do while not rs.eof and i<100
		i=i+1
		response.write rs("id")&":"&rs("sitename")&"<br />"&vbCrlf
		rs.movenext
	loop
	rs.close
	set rs=nothing

next
%>

至于getRows,這種方法只能算是返回結果的優化,并不能算是一種方法。我們采用兩種返回結果的方式測試。test3.asp采用set rs=server.createobject(“ADODB.recordset”)的方法,test4.asp采用set rs=conn.execute(sql)的方法


< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",conn,1,1
	rs.pagesize=100
	rs.absolutepage=6000+k
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&":"&res(1,i)&"<br />"&vbCrlf
	next

next
%>


< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=conn.execute("select * from site")
	rs.movefirst
	rs.move (6000+k)*100
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&":"&res(1,i)&"<br />"&vbCrlf
	next

next
%>

下面是我的測試結果:

test1.asp test2.asp test3.asp test4.asp
第一次測試 4281.25毫秒 20656.25毫秒 4281.25毫秒 18671.88毫秒
第二次測試 4234.375毫秒 25171.88毫秒 4312.5毫秒 13781.25毫秒
第三次測試 4328.125毫秒 20031.25毫秒 4234.375毫秒 19093.75毫秒

為什么會出現這種結果呢?set rs=conn.execute(sql),set rs=server.createobject(“ADODB.recordset”)為什么為相差這么多?對比一下test1.asp、test3.asp與test2.asp、test4.asp,除了返回結果的方式不同,還有一處就是rs.move。難道是這個原因?把test3.asp的代碼稍微修改一下。存為test5.asp。


< %
for k=0 to 100
	response.write "<br /><br />第"&(6000+k)&"頁<hr />"

	set rs=server.createobject("adodb.recordset")
	rs.open "select * from site",conn,1,1
	rs.movefirst
	rs.move (6000+k)*100
	res=rs.getRows(100)
	rs.close
	set rs=nothing
	for i=0 to 99
		response.write res(0,i)&":"&res(1,i)&"<br />"&vbCrlf
	next

next
%>

經過測試,test5.asp能比test3.asp快0.1~0.2秒,如果讀取100條數據,這點差距可以忽略不計。

由此可見:set rs=conn.execute的方式確實比set rs=server.createobject(“ADODB.recordset”)方式慢,在學校的時候,老師教的一般都是set rs=server.createobject(“ADODB.recordset”)的方法,真正工作室,學習所謂的高手set rs=conn.execute優化的方法,結果最終發現,而鄙視用老師教的方法寫程序的同行,最終發現還是老師教的速度快,而且set rs=server.createobject(“ADODB.recordset”)的方法比set rs=conn.execute的方法快4~5倍。囧。。。。貓七(苗啟源)博客首發,轉載請注明出處,原文地址: (http://www.okfdzs1868.com/p/conn-execute_rs-getrows)。

難道set rs=conn.execute就一無是處了嗎?在數據插入方面,兩者的差別有多大呢?詳情請關注我的博客(http://www.okfdzs1868.com)今天太累了,就寫這些吧~