#
對UUID幾乎沒有了解,google了一下,才知道是128位整數(shù)(16字節(jié))的全局唯一標識符(Universally Unique Identifier)。
UUID是指在一臺機器上生成的數(shù)字,它保證對在同一時空中的所有機器都是唯一的。通常平臺會提供生成UUID的API。UUID按照開放軟件基金會(OSF)制定的標準計算,用到了以太網(wǎng)卡地址、納秒級時間、芯片ID碼和許多可能的數(shù)字。由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關(guān),如果你在生成一個UUID之后,過幾秒又生成一個UUID,則第一個部分不同,其余相同),時鐘序列,全局唯一的IEEE機器識別號(如果有網(wǎng)卡,從網(wǎng)卡獲得,沒有網(wǎng)卡以其他方式獲得),UUID的唯一缺陷在于生成的結(jié)果串會比較長。關(guān)于UUID這個標準使用最普遍的是微軟的GUID(Globals Unique Identifiers)。
在ColdFusion中可以用CreateUUID()函數(shù)很簡單的生成UUID,其格式為:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每個 x 是 0-9 或 a-f 范圍內(nèi)的一個十六進制的數(shù)字。而標準的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
,可以從
cflib?下載
CreateGUID() UDF進行轉(zhuǎn)換。
使用UUID的好處在分布式的軟件系統(tǒng)中(比如:DCE/RPC, COM+,CORBA)就能體現(xiàn)出來,它能保證每個節(jié)點所生成的標識都不會重復,并且隨著WEB服務等整合技術(shù)的發(fā)展,UUID的優(yōu)勢將更加明顯。
關(guān)于UUID的更多信息可以多
google?一下。
 |
|
 |
Oracle9i 2.0.4在Red Hat Enterprise Linux AS 3上的安裝
|
|
|
Oracle9i 2.0.4在Red Hat Enterprise Linux AS 3上的安裝 (我測試了兩遍都OK) 1、確認安裝了以下軟件包 [oracle@Gledeson oracle]$ rpm -qa | grep openmotif openmotif21-2.1.30-8 openmotif-devel-2.2.3-3.RHEL3 openmotif-2.2.3-3.RHEL3 [oracle@Gledeson oracle]$ rpm -qa |grep setarch setarch-1.3-1 [oracle@Gledeson oracle]$ rpm -qa|grep compat compat-gcc-c++-7.3-2.96.128 compat-glibc-7.x-2.2.4.32.6 compat-slang-1.4.5-5 compat-pwdb-0.62-3 compat-libstdc++-devel-7.3-2.96.128 compat-db-4.0.14-5 compat-gcc-7.3-2.96.128 compat-libstdc++-7.3-2.96.128
2、建立Oracle帳號 groupadd dba groupadd oinstall useradd -c "Oracle software owner" -g oinstall -G dba oracle passwd oracle 3、建立文件目錄 su root mkdir /u01 mkdir /u01/oracle mkdir /u01/oracle/product mkdir /u01/oracle/product/9.2.0 chown -R oracle.oinstall /u01/oracle mkdir /var/opt/oracle chown oracle.dba /var/opt/oracle chmod 755 /var/opt/oracle 4、設(shè)置環(huán)境變量 用Oracle帳號執(zhí)行下列命令:(或直接copy到.bash_profile文件中) # Set the LD_ASSUME_KERNEL environment variable only for Red Hat 9, # RHEL AS 3, and RHEL AS 4 !! # Use the "Linuxthreads with floating stacks" implementation instead of NPTL: #export LD_ASSUME_KERNEL=2.4.1 # for RH 9 and RHEL AS 3 #export LD_ASSUME_KERNEL=2.4.19 # for RHEL AS 4 export LD_ASSUME_KERNEL=2.4.1 export ORACLE_BASE=/u01/oracle export ORACLE_HOME=$ORACLE_BASE/product/9.2.0 export ORACLE_SID=ORADB01 export ORACLE_TERM=xterm export ORA_NLS33=$ORACLE_HOME/ocommon/nls/admin/data LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib export LD_LIBRARY_PATH # Set shell search paths export PATH=$PATH:$ORACLE_HOME/bin 保存后退出. 執(zhí)行: source .bash_profile 然后。退出登錄,再次進入,這時候oracle的環(huán)境就已經(jīng)生效了 5、設(shè)置內(nèi)核參數(shù) su root 修改 /etc/sysctl.conf 這個文件,加入以下的語句: kernel.shmmax = 2147483648 kernel.shmmni = 4096 kernel.shmall = 2097152 kernel.sem = 250 32000 100 128 fs.file-max = 65536 net.ipv4.ip_local_port_range = 1024 65000 參數(shù)說明: sem 4個參數(shù)依次為SEMMSL(每個用戶擁有信號量最大數(shù)); SEMMNS(系統(tǒng)信號量最大數(shù)); SEMOPM(每次semopm系統(tǒng)調(diào)用操作數(shù)); SEMMNI(系統(tǒng)辛苦量集數(shù)最大數(shù)). Shmmax 最大共享內(nèi)存2GB 物理內(nèi)存如果小的話可以設(shè)置成 536870912. Shmmni 最小共享內(nèi)存 4096KB. Shmall 所有內(nèi)存大小. 6、安裝補丁 (ORACLE9i 9204版,只需在運行runInstall前打p3006854_9204_LINUX.zip 補丁即可, 其他補丁不用再打) 安裝補丁前,卻換到root用戶的控制臺,打補丁前執(zhí)行以下語句: su root mv /usr/bin/gcc /usr/bin/gcc323 ln -s /usr/bin/gcc296 /usr/bin/gcc mv /usr/bin/g++296 /usr/bin/g++ ln -s /usr/bin/g++ /usr/bin/g++296 [root@localhost /]# sh rhel3_pre_install.sh Applying patch... Ensuring permissions are correctly set... Done. Patch successfully applied 7、解壓文件 zcat ship_9204_linux_disk1.cpio | cpio -idmv zcat ship_9204_linux_disk2.cpio | cpio -idmv zcat ship_9204_linux_disk3.cpio | cpio -idmv 這時生成三個目錄:Disk1、Disk2、Disk3 8、cd到Disk1中 cd /Disk1 ./runInstall.sh
| | |
對String的深刻理解
剛開始玩java,對其String類,使用有些感觸;
1、"abc"與new String("abc");
經(jīng)常會問到的面試題:String s = new String("abc");創(chuàng)建了幾個String Object?【如這里創(chuàng)建了多少對象? 和一道小小的面試題 】
這個問題比較簡單,涉及的知識點包括:
引用變量與對象的區(qū)別;
字符串文字"abc"是一個String對象;
文字池[pool of literal strings]和堆[heap]中的字符串對象。
一、引用變量與對象:除了一些早期的Java書籍和現(xiàn)在的垃圾書籍,人們都可以從中比較清楚地學習到兩者的區(qū)別。A aa;語句聲明一個類A的引用變量aa[我常常稱之為句柄],而對象一般通過new創(chuàng)建。所以題目中s僅僅是一個引用變量,它不是對象。[ref 句柄、引用與對象]
二、Java中所有的字符串文字[字符串常量]都是一個String的對象。有人[特別是C程序員]在一些場合喜歡把字符串"當作/看成"字符數(shù)組,這也沒有辦法,因為字符串與字符數(shù)組存在一些內(nèi)在的聯(lián)系。事實上,它與字符數(shù)組是兩種完全不同的對象。
System.out.println("Hello".length());
char[] cc={'H','i'};
System.out.println(cc.length);
三、字符串對象的創(chuàng)建:由于字符串對象的大量使用[它是一個對象,一般而言對象總是在heap分配內(nèi)存],Java中為了節(jié)省內(nèi)存空間和運行時間[如比較字符串時,==比equals()快],在編譯階段就把所有的字符串文字放到一個文字池[pool of literal strings]中,而運行時文字池成為常量池的一部分。文字池的好處,就是該池中所有相同的字符串常量被合并,只占用一個空間。我們知道,對兩個引用變量,使用==判斷它們的值[引用]是否相等,即指向同一個對象:
String s1 = "abc" ;
String s2 = "abc" ;
if( s1 == s2 )
System.out.println("s1,s2 refer to the same object");
else System.out.println("trouble");
這里的輸出顯示,兩個字符串文字保存為一個對象。就是說,上面的代碼只在pool中創(chuàng)建了一個String對象。
現(xiàn)在看String s = new String("abc");語句,這里"abc"本身就是pool中的一個對象,而在運行時執(zhí)行new String()時,將pool中的對象復制一份放到heap中,并且把heap中的這個對象的引用交給s持有。ok,這條語句就創(chuàng)建了2個String對象。
String s1 = new String("abc") ;
String s2 = new String("abc") ;
if( s1 == s2 ){ //不會執(zhí)行的語句}
這時用==判斷就可知,雖然兩個對象的"內(nèi)容"相同[equals()判斷],但兩個引用變量所持有的引用不同,
BTW:上面的代碼創(chuàng)建了幾個String Object? [三個,pool中一個,heap中2個。]
[Java2 認證考試學習指南 (第4版)( 英文版)p197-199有圖解。]
2、字符串的+運算和字符串轉(zhuǎn)換
字符串轉(zhuǎn)換和串接是很基礎(chǔ)的內(nèi)容,因此我以為這個問題簡直就是送分題。事實上,我自己就答錯了。
String str = new String("jf"); // jf是接分
str = 1+2+str+3+4;
一共創(chuàng)建了多少String的對象?[我開始的答案:5個。jf、new、3jf、3jf3、3jf34]
首先看JLS的有關(guān)論述:
一、字符串轉(zhuǎn)換的環(huán)境[JLS 5.4 String Conversion]
字符串轉(zhuǎn)換環(huán)境僅僅指使用雙元的+運算符的情況,其中一個操作數(shù)是一個String對象。在這一特定情形下,另一操作數(shù)轉(zhuǎn)換成String,表達式的結(jié)果是這兩個String的串接。
二、串接運算符[JLS 15.18.1 String Concatenation Operator + ]
如果一個操作數(shù)/表達式是String類型,則另一個操作數(shù)在運行時轉(zhuǎn)換成一個String對象,并兩者串接。此時,任何類型都可以轉(zhuǎn)換成String。[這里,我漏掉了"3"和"4"]
如果是基本數(shù)據(jù)類型,則如同首先轉(zhuǎn)換成其包裝類對象,如int x視為轉(zhuǎn)換成Integer(x)。
現(xiàn)在就全部統(tǒng)一到引用類型向String的轉(zhuǎn)換了。這種轉(zhuǎn)換如同[as if]調(diào)用該對象的無參數(shù)toString方法。[如果是null則轉(zhuǎn)換成"null"]。因為toString方法在Object中定義,故所有的類都有該方法,而且Boolean, Character, Integer, Long, Float, Double, and String改寫了該方法。
關(guān)于+是串接還是加法,由操作數(shù)決定。1+2+str+3+4 就很容易知道是"3jf34"。[BTW :在JLS的15.18.1.3中舉的一個jocular little example,真的很無趣。]
下面的例子測試了改寫toString方法的情況.。
class A{
int i = 10;
public static void main(String []args){
String str = new String("jf");
str += new A();
System.out.print(str);
}
public String toString(){
return " a.i ="+i+"\n";
}
}
三、字符串轉(zhuǎn)換的優(yōu)化
按照上述說法,str = 1+2+str+3+4;語句似乎應該就應該生成5個String對象:
1+2 =3,then 3→Integer(3)→"3" in pool? [假設(shè)如此]
"3"+str(in heap) = "3jf" (in heap)
"3jf" +3 ,first 3→Integer(3)→"3" in pool? [則不創(chuàng)建] then "3jf3"
"3jf3"+4 create "4" in pool
then "3jf34"
這里我并不清楚3、4轉(zhuǎn)換成字符串后是否在池中,所以上述結(jié)果仍然是猜測。
為了減少創(chuàng)建中間過渡性的字符串對象,提高反復進行串接運算時的性能,a Java compiler可以使用StringBuffer或者類似的技術(shù),或者把轉(zhuǎn)換與串接合并成一步。例如:對于 a + b + c ,Java編譯器就可以將它視為[as if]
new StringBuffer().append(a).append(b).append(c).toString();
注意,對于基本類型和引用類型,在append(a)過程中仍然要先將參數(shù)轉(zhuǎn)換,從這個觀點看,str = 1+2+str+3+4;創(chuàng)建的字符串可能是"3"、"4"和"3jf34"[以及一個StringBuffer對象]。
現(xiàn)在我仍然不知道怎么回答str = 1+2+str+3+4;創(chuàng)建了多少String的對象,。或許,這個問題不需要過于研究,至少SCJP不會考它。
3、這又不同:str = "3"+"jf"+"3"+"4";
如果是一個完全由字符串文字組成的表達式,則在編譯時,已經(jīng)被優(yōu)化而不會在運行時創(chuàng)建中間字符串。測試代碼如下:
String str1 ="3jf34";
String str2 ="3"+"jf"+"3"+"4";
if(str1 == str2) {
System.out.println("str1 == str2");
}else {
System.out.println("think again");
}
if(str2.equals(str1))
System.out.println("yet str2.equals(str1)");
可見,str1與str2指向同一個對象,這個對象在pool中。所有遵循Java Language Spec的編譯器都必須在編譯時對constant expressions 進行簡化。JLS規(guī)定:Strings computed by constant expressions (ý15.28) are computed at compile time and then treated as if they were literals.
對于String str2 ="3"+"jf"+"3"+"4";我們說僅僅創(chuàng)建一個對象。注意,“創(chuàng)建多少對象”的討論是說運行時創(chuàng)建多少對象。
BTW:編譯時優(yōu)化
String x = "aaa " + "bbb ";
if (false) {
x = x + "ccc ";
}
x += "ddd ";
等價于:
String x = "aaa bbb ";
x = x + "ddd ";
4、不變類
String對象是不可改變的(immutable)。有人對str = 1+2+str+3+4;語句提出疑問,怎么str的內(nèi)容可以改變?其實仍然是因為不清楚:引用變量與對象的區(qū)別。str僅僅是引用變量,它的值——它持有的引用可以改變。你不停地創(chuàng)建新對象,我就不斷地改變指向。[參考TIJ的Read-only classes。]
不變類的關(guān)鍵是,對于對象的所有操作都不可能改變原來的對象[只要需要,就返回一個改變了的新對象]。這就保證了對象不可改變。為什么要將一個類設(shè)計成不變類?有一個OOD設(shè)計的原則:Law of Demeter。其廣義解讀是:
使用不變類。只要有可能,類應當設(shè)計為不變類。
1、tomcat下配置虛擬目錄
打開TOMCAT文件下的conf\server.xml文件 ,查找到<ContextManager>標簽,并在該標簽的結(jié)束標簽</ContextManager>前面加上:
<Context path="虛擬目錄" docBase="硬盤目錄" debug="0" reloadable="true" crossContext="true"/>
其中path的值是虛擬目錄,docbase的值是你的硬盤的的目錄的絕對路徑。
如找不到<ContextManager>元素,可以找
<Host name="localhost" debug="0" appBase="webapps"
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
然后添加<Context path="虛擬目錄" docBase="硬盤目錄" debug="0" reloadable="true" crossContext="true"/>
2、禁止tomcat目錄瀏覽,將listings設(shè)為false
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>
org.apache.catalina.servlets.DefaultServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
3、設(shè)置友好錯誤頁面,配置web.xml
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
4、在IE中直接打開其他擴展名的文件
為了讓能在IE瀏覽器中自動打開其他擴展文件名的文件的設(shè)置:
需要在WEB.XML中進行如下的設(shè)置:
在WEB.XML中添加<mime-mapping>,其中:
<extension>: 文件的擴展名
<mime-type>: 除了該類型文件的可執(zhí)行文件,同WINDOW注冊表中的 /HKEY_CLASSES_ROOT下該類文件的Content Type 的值一樣.
如能在IE中自動打開DOC,XLS,PDF文件的配置如下:
<?xml version="1.0" ?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 1.2//EN" "<web-app>
<mime-mapping>
<extension>doc</extension>
<mime-type>application/msword</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xls</extension>
<mime-type>application/msexcel</mime-type>
</mime-mapping>
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
</web-app>
- 確保運行 SQL Server 的服務器上的 Oracle 客戶端軟件已達到提供程序所要求的級別。用于 Oracle 的 Microsoft OLE DB 提供程序要求 Oracle 客戶端軟件支持文件的版本為 7.3.3.4.0 或更高版本,并且 SQL*Net 的版本為 2.3.3.0.4。
- 在運行 SQL Server 的服務器上創(chuàng)建指向 Oracle 數(shù)據(jù)庫實例的 SQL*Net 別名。有關(guān)更多信息,請參見 Oracle 文檔。
- 執(zhí)行 sp_addlinkedserver 創(chuàng)建鏈接服務器,指定 MSDAORA 為 provider_name,指定用于 Oracle 數(shù)據(jù)庫實例的 SQL*Net 別名為 data_ source。
以下示例假設(shè)已將一個 SQL*Net 別名定義為 OracleDB。
sp_addlinkedserver 'OrclDB', 'Oracle', 'MSDAORA', 'OracleDB'
- 使用 sp_addlinkedsrvlogin 創(chuàng)建從 SQL Server 登錄到 Oracle 登錄的登錄映射。
以下示例通過 Oracle 登錄名 OrclUsr 和密碼 OrclPwd 將 SQL Server 登錄 Joe 映射到步驟 3 中定義的鏈接服務器:
sp_addlinkedsrvlogin 'OrclDB', false, 'Joe', 'OrclUsr', 'OrclPwd'
每個 Oracle 數(shù)據(jù)庫實例僅有一個名稱為空的目錄。Oracle 鏈接服務器中的表必須使用四部分名稱格式 OracleLinkedServerName..OwnerUserName.TableName 進行引用。例如,以下 SELECT 語句引用 Oracle 用戶 MARY 在 OrclDB 鏈接服務器映射的服務器上所擁有的表 SALES。
SELECT *
FROM OrclDB..MARY.SALES
注意需要 修改 注冊表 :對于win2k/oracle 8i ,修改的內(nèi)容為:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI]
"OracleXaLib"="oraclient8.dll"
"OracleSqlLib"="orasql8.dll"
"OracleOciLib"="oci.dll"
其它事項:啟動mstdc服務
說明:
建議在剛安裝完的時候進行修改,對已經(jīng)投產(chǎn)的系統(tǒng),風險太大!
步驟如下:
1. Make sure the parallel_server parameter in INIT.ORA is set to false
or it is not set at all.
2. Execute the following commands in Server Manager (svrmgrl):
SVRMGR> SHUTDOWN IMMEDIATE; -- or NORMAL
SVRMGR> STARTUP MOUNT;
SVRMGR> ALTER SYSTEM ENABLE RESTRICTED SESSION;
SVRMGR> ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
SVRMGR> ALTER SYSTEM SET AQ_TM_PROCESSES=0;
SVRMGR> ALTER DATABASE OPEN;
SVRMGR> ALTER DATABASE [NATIONAL] CHARACTER SET INTERNAL_USE ;
SVRMGR> SHUTDOWN IMMEDIATE; -- OR NORMAL
SVRMGR> STARTUP RESTRICT;
3. Restore the parallel_server parameter in INIT.ORA, if necessary.
4. Execute the following commands in Server Manager:
SVRMGR> SHUTDOWN IMMEDIATE; -- OR NORMAL
SVRMGR> STARTUP;
如果沒有登陸,首先執(zhí)行
SVRMGR> connect internal;
軟件環(huán)境:
1、Windows 2000+ORACLE
2、ORACLE安裝路徑為:C:\ORACLE
實現(xiàn)方法:
1、 開始->設(shè)置->控制面板->管理工具->服務停止所有Oracle服務。
2、 開始->程序->Oracle - OraHome81->Oracle Installation Products->Universal Installer卸裝所有Oracle產(chǎn)品,但Universal Installer本身不能被刪除
5、 運行regedit,選擇HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE,按del鍵刪除這個入口。
6、 運行regedit,選擇HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,滾動這個列表,刪除所有Oracle入口。
7、 運行refedit,HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application,
刪除所有Oracle入口。
8、 開始->設(shè)置->控制面板->系統(tǒng)->高級->環(huán)境變量刪除環(huán)境變量CLASSPATH和PATH中有關(guān)Oracle的設(shè)定
9、 從桌面上、STARTUP(啟動)組、程序菜單中,刪除所有有關(guān)Oracle的組和圖標
10、 刪除\Program Files\Oracle目錄
11、 重新啟動計算機,重起后才能完全刪除Oracle所在目錄
12、 刪除與Oracle有關(guān)的文件,選擇Oracle所在的缺省目錄C:\Oracle,刪除這個入口目錄及所有子目錄,并從C:\WINNT下刪除以下文件ORACLE.INI、oradim73.INI、oradim80.INI、oraodbc.ini等等。
13、 WIN.INI文件中若有[ORACLE]的標記段,刪除該段
14、 如有必要,刪除所有Oracle相關(guān)的ODBC的DSN
15、 到事件查看器中,刪除Oracle相關(guān)的日志
說明:
如果有個別DLL文件無法刪除的情況,則不用理會,重新啟動,開始新的安裝,安裝時,選擇一個新的目錄,則,安裝完畢并重新啟動后,老的目錄及文件就可以刪除掉了。
pro*c and vc++ error
From the oracle metalink -
Problem Description
-------------------
You are trying to compile a precompiled Pro*C application.
You are using Microsoft Visual C++ 6.0. At compile time,
you get the error message:
C2079: 'SQLSTM" uses undefined struct 'SQLEXD'
Solution Description
--------------------
In Visual C++, under Project -> Settings -> Precompiled Headers,
set this to "Automatic Use of Precompiled Headers", with the "Through
Header"
option left blank.
HTH.,
Ora600
"Glen"
wrote in message
news:69867261.0110312021.3ba2f3ee@posting.google.com...
> Hi,
>
> I have precompiled some pro*c code which worked fine and outputted a
> c++ file which is included in my project. I have included the
> orasql8.lib and when I try to compile the project receive the
> following error:
>
> error C2079: 'sqlstm' uses undefined struct 'sqlexd'
>
> I don't understand why, the following code appears before where the
> error is encountered.
>
> static struct sqlexd {
> unsigned int sqlvsn;
> unsigned int arrsiz;
> unsigned int iters;
> unsigned int offset;
> unsigned short selerr;
> unsigned short sqlety;
> unsigned int occurs;
> const short *cud;
> unsigned char *sqlest;
> const char *stmt;
> sqladts *sqladtp;
> sqltdss *sqltdsp;
> void **sqphsv;
> unsigned int *sqphsl;
> int *sqphss;
> void **sqpind;
> int *sqpins;
> unsigned int *sqparm;
> unsigned int **sqparc;
> unsigned short *sqpadto;
> unsigned short *sqptdso;
> void *sqhstv[4];
> unsigned int sqhstl[4];
> int sqhsts[4];
> void *sqindv[4];
> int sqinds[4];
> unsigned int sqharm[4];
> unsigned int *sqharc[4];
> unsigned short sqadto[4];
> unsigned short sqtdso[4];
> } sqlstm = {10,4};
>
> If anyone has any ideas i would be most appreciative.
>
> Cheers
> Glen
用VC開發(fā)基于ORACLE數(shù)據(jù)庫方法 |
作者:黎杰 麥中凡 更新時間: 2005-05-07 |
|
|
1. 引言 ORACLE 公司自1979 年推出基于SQL 標準的關(guān)系數(shù)據(jù)庫產(chǎn)品到1997 年版本8 的推出,ORACLE 數(shù)據(jù)庫以其支持大數(shù)據(jù)庫、多用戶的高性能事務處理,對業(yè)界各項工業(yè)標準的支持,完整的安全和完整性控制,支持分布式數(shù)據(jù)庫和分布處理,具有可移植性、可兼容性和可連接性等突出優(yōu)點倍受用戶喜愛,根據(jù)IDG1992 年全球UNIX 數(shù)據(jù)庫的市場報告,ORACLE 占市場銷售量的50%。而在客戶端的開發(fā)工具方面,Visual C++ 也因其強大的功能和高度的靈活性等特點深受廣大程序員的喜愛,因此本文旨在介紹使用Visual C++ 開發(fā)基于ORACLE 數(shù)據(jù)庫應用程序的兩種方法。
2. 使用PRO*C 開發(fā)數(shù)據(jù)庫應用
2.1 PRO*C 工作原理
PRO 系列是ORACLE 公司提供的在第三代高級程序設(shè)計語言中嵌入SQL 語句來訪問數(shù)據(jù)庫的一套預編譯程序,包括PRO*Ada、PRO*C、PRO*COBOL、PRO*Fortran、PRO*Pascal 和PRO*PL/I 六種。程序員用相應的高級語言編寫嵌入SQL 語句的PRO 源程序(若用C 語言則稱為PRO*C 源程序)后運行相應的預編譯程序,把嵌入的SQL 語句轉(zhuǎn)換為標準的ORACLE 調(diào)用并生成目標源程序,即純高級語言格式的源程序,然后就可以將這些源程序加入用戶的程序中調(diào)用,其處理過程如下圖。
ORACLE 預編譯程序提供如下功能:
⑴能用六種通用的高級程序設(shè)計語言中的任何一種編寫應用程序。
⑵遵循ANSI 標準,在高級語言中嵌入SQL 語句。
⑶可采用動態(tài)SQL 方法,讓程序在運行時接受或構(gòu)造一個有效的SQL 語句。
⑷實現(xiàn)ORACLE 內(nèi)部數(shù)據(jù)類型和高級語言數(shù)據(jù)類型之間的自動轉(zhuǎn)換。
⑸可通過在應用程序中嵌入PL/SQL 事物處理塊來改進性能。
⑹能在程序行和命令行上指定所需要的預編譯可選項,并可在預編譯的過程中改變它們的值。
⑺能全面檢查嵌入的SQL 數(shù)據(jù)操縱語句和PL/SQL 塊的文法和語義。
⑻可用SQL*Net 并行存取多個地點的ORACLE 數(shù)據(jù)庫。
⑼可把數(shù)組作為輸入和輸出程序變量使用。
⑽能對應用程序中的代碼段進行條件預編譯。
⑾提供了較強的異常處理功能。
由此可見,通過預編譯程序與其它高級語言的結(jié)合,既可以利用SQL 強有力的功能和靈活性為數(shù)據(jù)庫應用系統(tǒng)的開發(fā)提供強有力的手段,又可以充分利用高級語言自身在系統(tǒng)開發(fā)方面的優(yōu)勢,從而提供一個完備的基于ORACLE 數(shù)據(jù)庫應用程序的開發(fā)解決方案。
2.2 在VC 中使用PRO*C
每個PRO*C 源文件一般由程序頭和程序體兩部分組成。程序頭包含宿主變量(SQL 語句中所包含的變量)說明、通訊區(qū)定義和C 外部表示符的說明等。程序體一般是由若干函數(shù)組成,這些函數(shù)內(nèi)含有SQL 語句(以EXEC SQL 起頭的語句)。
PRO*C 支持的數(shù)據(jù)類型包括VARCHAR2( 變長字符串)、NUMBER( 二進制數(shù))、INTGER( 有符號整數(shù))、FLOAT( 浮點數(shù))、STRING( 以NULL 結(jié)尾的字符串)、VARNUM( 變長二進制數(shù))、LONG( 變長字符串)、VARCHAR( 變長字符串)、ROWID( 二進制值)、DATE( 定長日期/ 時間值)、VARRAW( 變長二進制數(shù)據(jù))、RAW( 定長二進制數(shù)據(jù)) 、LONGRAW( 變長二進制數(shù)據(jù))、UNSIGNED( 無符號整數(shù))、LONGVARCHAR( 變長字符串)、LONGVARRAW( 變長二進制數(shù)據(jù))、CHAR( 定長字符串)、CHARZ(C 中定長以NULL 結(jié)尾的字符串)、MLSLABEL( 變長二進制數(shù)據(jù))。
在PRO*C 中不能使用'l' 或'u' 作詞尾或'0x' 作詞頭修飾常量;在SQL 語句中使用單引號來定義字符串,用雙引號來定義特殊的或小寫字符的標識符( 如表名等);SQL 語句中不允許使用C 中的尋址、間接、位邏輯、復合賦值、?=、-、++、%、<<、>> 操作符并且用NOT、AND、OR、= 代替!、&&、||、==。
下面的程序是一個聯(lián)結(jié)數(shù)據(jù)庫的PRO*C 源程序例子。
#include < sqlca.h > //聲明SQL通訊區(qū) #include < string.h > #include < afxwin.h > EXEC SQL BEGIN DECLARE SECTION; VARCHAR username[20]; //聲明宿主變量 VARCHAR password[20]; VARCHAR dbname[20]; EXEC SQL END DECLARE SECTION; void db_connect() { strcpy((char *)username.arr,"SCOTT"); username.len = strlen((char *)username.arr); strcpy((char *)password.arr,"TIGER"); password.len = strlen((char *)password.arr); strcpy((char *)dbname.arr,"SUNDB"); dbname.len = strlen((char *)dbname.arr); EXEC SQL WHENEVER SQLERROR STOP; //隱式異常處理 EXEC SQL CONNECT :username IDENTIFIED BY :password USING :dbname; /*if (sqlca.sqlcode != 0) //顯式異常處理 { AfxMessageBox("\n與Oracle數(shù)據(jù)庫連接失敗!"); return; }*/ }
在VC 中使用PRO*C 時,先用PRO*C 編寫所需的操作數(shù)據(jù)庫的子程序,再運行PRO*C 預編譯程序把PRO*C 源程序轉(zhuǎn)成相應的CPP 源程序,將該程序插入到用戶工程文件中并在需要對插入函數(shù)進行調(diào)用的模塊中說明函數(shù),然后就可以在此模塊中調(diào)用所需的函數(shù)。
3. 使用ODBC 中間件訪問數(shù)據(jù)庫
3.1 ODBC 工作原理
DBC 是Open Database Connect 即開放數(shù)據(jù)庫互連的簡稱,它是由Microsoft 公司于1991 年提出的一個用于訪問數(shù)據(jù)庫的統(tǒng)一界面標準,是應用程序和數(shù)據(jù)庫系統(tǒng)之間的中間件。它通過使用相應應用平臺上和所需數(shù)據(jù)庫對應的驅(qū)動程序與應用程序的交互來實現(xiàn)對數(shù)據(jù)庫的操作,避免了在應用程序中直接調(diào)用與數(shù)據(jù)庫相關(guān)的操作,從而提供了數(shù)據(jù)庫的獨立性。
ODBC 主要由驅(qū)動程序和驅(qū)動程序管理器組成。驅(qū)動程序是一個用以支持ODBC 函數(shù)調(diào)用的模塊(在WIN95 下通常是一個DLL),每個驅(qū)動程序?qū)谙鄳臄?shù)據(jù)庫,當應用程序從基于一個數(shù)據(jù)庫系統(tǒng)移植到另一個時,只需更改應用程序中由ODBC 管理程序設(shè)定的與相應數(shù)據(jù)庫系統(tǒng)對應的別名即可。驅(qū)動程序管理器(包含在ODBC32.DLL 中)可鏈接到所有ODBC 應用程序中,它負責管理應用程序中ODBC 函數(shù)與DLL 中函數(shù)的綁定。
ODBC 使用層次的方法來管理數(shù)據(jù)庫,在數(shù)據(jù)庫通信結(jié)構(gòu)的每一層,對可能出現(xiàn)依賴數(shù)據(jù)庫產(chǎn)品自身特性的地方,ODBC 都引入一個公共接口以解決潛在的不一致性,從而很好地解決了基于數(shù)據(jù)庫系統(tǒng)應用程序的相對獨立性,這也是ODBC 一經(jīng)推出就獲得巨大成功的重要原因之一。
從結(jié)構(gòu)上分,ODBC 分為單束式和多束式兩類。
⑴單束式驅(qū)動程序
單束式驅(qū)動程序介于應用程序和數(shù)據(jù)庫之間,像中介驅(qū)動程序一樣數(shù)據(jù)提供一個統(tǒng)一的數(shù)據(jù)訪問方式。
當用戶進行數(shù)據(jù)庫操作時,應用程序傳遞一個ODBC 函數(shù)調(diào)用給ODBC 驅(qū)動程序管理器,由ODBC API 判斷該調(diào)用是由它直接處理并將結(jié)果返回還是送交驅(qū)動程序執(zhí)行并將結(jié)果返回。
由上可見,單束式驅(qū)動程序本身是一個數(shù)據(jù)庫引擎,由它直接可完成對數(shù)據(jù)庫的操作,盡管該數(shù)據(jù)庫可能位于網(wǎng)絡(luò)的任何地方。
⑵多束式驅(qū)動程序
多束式驅(qū)動程序負責在數(shù)據(jù)庫引擎和客戶應用程序之間傳送命令和數(shù)據(jù),它本身并不執(zhí)行數(shù)據(jù)處理操作而用于遠程操作的網(wǎng)絡(luò)通信協(xié)議的一個界面。
前端應用程序提出對數(shù)據(jù)庫處理的請求,該請求轉(zhuǎn)給ODBC 驅(qū)動程序管理器,驅(qū)動程序管理器依據(jù)請求的情況,就地完成或傳給多束驅(qū)動程序,多束式驅(qū)動程序?qū)⒄埱蠓g為特定廠家的數(shù)據(jù)庫通信接口(如Oracle 的SQLNet)所能理解的形式并交于接口去處理,接口把請求經(jīng)網(wǎng)絡(luò)傳送給服務器上的數(shù)據(jù)引擎,服務器處理完后把結(jié)果發(fā)回給數(shù)據(jù)庫通信接口,數(shù)據(jù)庫接口將結(jié)果傳給多束式ODBC 驅(qū)動程序,再由驅(qū)動程序?qū)⒔Y(jié)果傳給應用程序。
3.2 在VC 中使用ODBC
Visual C++ 中提供了CDatabase、CRecordset、CRecordView、CDBException 和CFieldExchange 五個類,這些類封裝了ODBC SDK 函數(shù),從而使用戶可以無需了解SDK 函數(shù)就可以很方便地操作支持ODBC 的數(shù)據(jù)庫。
CDatabase 類:封裝了與數(shù)據(jù)庫建立連接,控制事務的提交和回滾及執(zhí)行SQL 語句的方法。
CRecordset 類:封裝了大部分操縱數(shù)據(jù)庫的方法,包括瀏覽、修改記錄,控制游標移動,排序等操作。
CRecordView 類:提供了與recordset 對象相連接的視,可以建立視中的控件與數(shù)據(jù)庫數(shù)據(jù)的對應,同時支持移動游標,修改記錄等操作。
CDBException 類:提供了對數(shù)據(jù)庫操作的異常處理,可以獲得操作異常的相關(guān)返回代碼。
CFieldExchange 類:提供了用戶變量與數(shù)據(jù)庫字段之間的數(shù)據(jù)交換,如果不需要使用自定義類型,你將不用直接調(diào)用該類的函數(shù),MFC Wizard 將自動為程序員建立連接。
4. 兩種方法的比較
綜上所述,使用這兩種方法在Visual C++ 中都可以很方便地開發(fā)出基于ORACLE 數(shù)據(jù)庫的應用程序,同時,這兩種方法又各有其優(yōu)缺點。ODBC 由于有MFC 強大的類庫支持而使得編程實現(xiàn)非常方便,同時可移植性也很強,在異構(gòu)的數(shù)據(jù)庫之間移植也只需更改很少的一部分程序,但是,由ODBC 的實現(xiàn)機制我們可以看到,與PRO*C 相比,應用程序需要經(jīng)過ODBC 驅(qū)動程序管理器和ODBC 驅(qū)動程序兩層才能和數(shù)據(jù)庫通信接口建立聯(lián)系,而PRO*C 是直接與通信接口聯(lián)系,因此建立在ODBC 上應用程序的執(zhí)行效率會相對低一些。PRO*C 具有執(zhí)行效率高,支持嵌入式PL/SQL 塊等ORACLE 自身特有的優(yōu)點,但正因為有了這些優(yōu)點,使得用PRO*C 開發(fā)出的應用程序無法向異構(gòu)數(shù)據(jù)庫平臺移植。 | |