#
對UUID幾乎沒有了解,google了一下,才知道是128位整數(16字節)的全局唯一標識符(Universally Unique Identifier)。
UUID是指在一臺機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。通常平臺會提供生成UUID的API。UUID按照開放軟件基金會(OSF)制定的標準計算,用到了以太網卡地址、納秒級時間、芯片ID碼和許多可能的數字。由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個UUID之后,過幾秒又生成一個UUID,則第一個部分不同,其余相同),時鐘序列,全局唯一的IEEE機器識別號(如果有網卡,從網卡獲得,沒有網卡以其他方式獲得),UUID的唯一缺陷在于生成的結果串會比較長。關于UUID這個標準使用最普遍的是微軟的GUID(Globals Unique Identifiers)。
在ColdFusion中可以用CreateUUID()函數很簡單的生成UUID,其格式為:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每個 x 是 0-9 或 a-f 范圍內的一個十六進制的數字。而標準的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
,可以從
cflib?下載
CreateGUID() UDF進行轉換。
使用UUID的好處在分布式的軟件系統中(比如:DCE/RPC, COM+,CORBA)就能體現出來,它能保證每個節點所生成的標識都不會重復,并且隨著WEB服務等整合技術的發展,UUID的優勢將更加明顯。
關于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、設置環境變量 用Oracle帳號執行下列命令:(或直接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 保存后退出. 執行: source .bash_profile 然后。退出登錄,再次進入,這時候oracle的環境就已經生效了 5、設置內核參數 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 參數說明: sem 4個參數依次為SEMMSL(每個用戶擁有信號量最大數); SEMMNS(系統信號量最大數); SEMOPM(每次semopm系統調用操作數); SEMMNI(系統辛苦量集數最大數). Shmmax 最大共享內存2GB 物理內存如果小的話可以設置成 536870912. Shmmni 最小共享內存 4096KB. Shmall 所有內存大小. 6、安裝補丁 (ORACLE9i 9204版,只需在運行runInstall前打p3006854_9204_LINUX.zip 補丁即可, 其他補丁不用再打) 安裝補丁前,卻換到root用戶的控制臺,打補丁前執行以下語句: 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");
經常會問到的面試題:String s = new String("abc");創建了幾個String Object?【如這里創建了多少對象? 和一道小小的面試題 】
這個問題比較簡單,涉及的知識點包括:
引用變量與對象的區別;
字符串文字"abc"是一個String對象;
文字池[pool of literal strings]和堆[heap]中的字符串對象。
一、引用變量與對象:除了一些早期的Java書籍和現在的垃圾書籍,人們都可以從中比較清楚地學習到兩者的區別。A aa;語句聲明一個類A的引用變量aa[我常常稱之為句柄],而對象一般通過new創建。所以題目中s僅僅是一個引用變量,它不是對象。[ref 句柄、引用與對象]
二、Java中所有的字符串文字[字符串常量]都是一個String的對象。有人[特別是C程序員]在一些場合喜歡把字符串"當作/看成"字符數組,這也沒有辦法,因為字符串與字符數組存在一些內在的聯系。事實上,它與字符數組是兩種完全不同的對象。
System.out.println("Hello".length());
char[] cc={'H','i'};
System.out.println(cc.length);
三、字符串對象的創建:由于字符串對象的大量使用[它是一個對象,一般而言對象總是在heap分配內存],Java中為了節省內存空間和運行時間[如比較字符串時,==比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中創建了一個String對象。
現在看String s = new String("abc");語句,這里"abc"本身就是pool中的一個對象,而在運行時執行new String()時,將pool中的對象復制一份放到heap中,并且把heap中的這個對象的引用交給s持有。ok,這條語句就創建了2個String對象。
String s1 = new String("abc") ;
String s2 = new String("abc") ;
if( s1 == s2 ){ //不會執行的語句}
這時用==判斷就可知,雖然兩個對象的"內容"相同[equals()判斷],但兩個引用變量所持有的引用不同,
BTW:上面的代碼創建了幾個String Object? [三個,pool中一個,heap中2個。]
[Java2 認證考試學習指南 (第4版)( 英文版)p197-199有圖解。]
2、字符串的+運算和字符串轉換
字符串轉換和串接是很基礎的內容,因此我以為這個問題簡直就是送分題。事實上,我自己就答錯了。
String str = new String("jf"); // jf是接分
str = 1+2+str+3+4;
一共創建了多少String的對象?[我開始的答案:5個。jf、new、3jf、3jf3、3jf34]
首先看JLS的有關論述:
一、字符串轉換的環境[JLS 5.4 String Conversion]
字符串轉換環境僅僅指使用雙元的+運算符的情況,其中一個操作數是一個String對象。在這一特定情形下,另一操作數轉換成String,表達式的結果是這兩個String的串接。
二、串接運算符[JLS 15.18.1 String Concatenation Operator + ]
如果一個操作數/表達式是String類型,則另一個操作數在運行時轉換成一個String對象,并兩者串接。此時,任何類型都可以轉換成String。[這里,我漏掉了"3"和"4"]
如果是基本數據類型,則如同首先轉換成其包裝類對象,如int x視為轉換成Integer(x)。
現在就全部統一到引用類型向String的轉換了。這種轉換如同[as if]調用該對象的無參數toString方法。[如果是null則轉換成"null"]。因為toString方法在Object中定義,故所有的類都有該方法,而且Boolean, Character, Integer, Long, Float, Double, and String改寫了該方法。
關于+是串接還是加法,由操作數決定。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";
}
}
三、字符串轉換的優化
按照上述說法,str = 1+2+str+3+4;語句似乎應該就應該生成5個String對象:
1+2 =3,then 3→Integer(3)→"3" in pool? [假設如此]
"3"+str(in heap) = "3jf" (in heap)
"3jf" +3 ,first 3→Integer(3)→"3" in pool? [則不創建] then "3jf3"
"3jf3"+4 create "4" in pool
then "3jf34"
這里我并不清楚3、4轉換成字符串后是否在池中,所以上述結果仍然是猜測。
為了減少創建中間過渡性的字符串對象,提高反復進行串接運算時的性能,a Java compiler可以使用StringBuffer或者類似的技術,或者把轉換與串接合并成一步。例如:對于 a + b + c ,Java編譯器就可以將它視為[as if]
new StringBuffer().append(a).append(b).append(c).toString();
注意,對于基本類型和引用類型,在append(a)過程中仍然要先將參數轉換,從這個觀點看,str = 1+2+str+3+4;創建的字符串可能是"3"、"4"和"3jf34"[以及一個StringBuffer對象]。
現在我仍然不知道怎么回答str = 1+2+str+3+4;創建了多少String的對象,?;蛟S,這個問題不需要過于研究,至少SCJP不會考它。
3、這又不同:str = "3"+"jf"+"3"+"4";
如果是一個完全由字符串文字組成的表達式,則在編譯時,已經被優化而不會在運行時創建中間字符串。測試代碼如下:
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規定: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";我們說僅僅創建一個對象。注意,“創建多少對象”的討論是說運行時創建多少對象。
BTW:編譯時優化
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的內容可以改變?其實仍然是因為不清楚:引用變量與對象的區別。str僅僅是引用變量,它的值——它持有的引用可以改變。你不停地創建新對象,我就不斷地改變指向。[參考TIJ的Read-only classes。]
不變類的關鍵是,對于對象的所有操作都不可能改變原來的對象[只要需要,就返回一個改變了的新對象]。這就保證了對象不可改變。為什么要將一個類設計成不變類?有一個OOD設計的原則:Law of Demeter。其廣義解讀是:
使用不變類。只要有可能,類應當設計為不變類。
1、tomcat下配置虛擬目錄
打開TOMCAT文件下的conf\server.xml文件 ,查找到<ContextManager>標簽,并在該標簽的結束標簽</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設為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、設置友好錯誤頁面,配置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瀏覽器中自動打開其他擴展文件名的文件的設置:
需要在WEB.XML中進行如下的設置:
在WEB.XML中添加<mime-mapping>,其中:
<extension>: 文件的擴展名
<mime-type>: 除了該類型文件的可執行文件,同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 的服務器上創建指向 Oracle 數據庫實例的 SQL*Net 別名。有關更多信息,請參見 Oracle 文檔。
- 執行 sp_addlinkedserver 創建鏈接服務器,指定 MSDAORA 為 provider_name,指定用于 Oracle 數據庫實例的 SQL*Net 別名為 data_ source。
以下示例假設已將一個 SQL*Net 別名定義為 OracleDB。
sp_addlinkedserver 'OrclDB', 'Oracle', 'MSDAORA', 'OracleDB'
- 使用 sp_addlinkedsrvlogin 創建從 SQL Server 登錄到 Oracle 登錄的登錄映射。
以下示例通過 Oracle 登錄名 OrclUsr 和密碼 OrclPwd 將 SQL Server 登錄 Joe 映射到步驟 3 中定義的鏈接服務器:
sp_addlinkedsrvlogin 'OrclDB', false, 'Joe', 'OrclUsr', 'OrclPwd'
每個 Oracle 數據庫實例僅有一個名稱為空的目錄。Oracle 鏈接服務器中的表必須使用四部分名稱格式 OracleLinkedServerName..OwnerUserName.TableName 進行引用。例如,以下 SELECT 語句引用 Oracle 用戶 MARY 在 OrclDB 鏈接服務器映射的服務器上所擁有的表 SALES。
SELECT *
FROM OrclDB..MARY.SALES
注意需要 修改 注冊表 :對于win2k/oracle 8i ,修改的內容為:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI]
"OracleXaLib"="oraclient8.dll"
"OracleSqlLib"="orasql8.dll"
"OracleOciLib"="oci.dll"
其它事項:啟動mstdc服務
說明:
建議在剛安裝完的時候進行修改,對已經投產的系統,風險太大!
步驟如下:
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;
如果沒有登陸,首先執行
SVRMGR> connect internal;
軟件環境:
1、Windows 2000+ORACLE
2、ORACLE安裝路徑為:C:\ORACLE
實現方法:
1、 開始->設置->控制面板->管理工具->服務停止所有Oracle服務。
2、 開始->程序->Oracle - OraHome81->Oracle Installation Products->Universal Installer卸裝所有Oracle產品,但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、 開始->設置->控制面板->系統->高級->環境變量刪除環境變量CLASSPATH和PATH中有關Oracle的設定
9、 從桌面上、STARTUP(啟動)組、程序菜單中,刪除所有有關Oracle的組和圖標
10、 刪除\Program Files\Oracle目錄
11、 重新啟動計算機,重起后才能完全刪除Oracle所在目錄
12、 刪除與Oracle有關的文件,選擇Oracle所在的缺省目錄C:\Oracle,刪除這個入口目錄及所有子目錄,并從C:\WINNT下刪除以下文件ORACLE.INI、oradim73.INI、oradim80.INI、oraodbc.ini等等。
13、 WIN.INI文件中若有[ORACLE]的標記段,刪除該段
14、 如有必要,刪除所有Oracle相關的ODBC的DSN
15、 到事件查看器中,刪除Oracle相關的日志
說明:
如果有個別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開發基于ORACLE數據庫方法 |
作者:黎杰 麥中凡 更新時間: 2005-05-07 |
|
|
1. 引言 ORACLE 公司自1979 年推出基于SQL 標準的關系數據庫產品到1997 年版本8 的推出,ORACLE 數據庫以其支持大數據庫、多用戶的高性能事務處理,對業界各項工業標準的支持,完整的安全和完整性控制,支持分布式數據庫和分布處理,具有可移植性、可兼容性和可連接性等突出優點倍受用戶喜愛,根據IDG1992 年全球UNIX 數據庫的市場報告,ORACLE 占市場銷售量的50%。而在客戶端的開發工具方面,Visual C++ 也因其強大的功能和高度的靈活性等特點深受廣大程序員的喜愛,因此本文旨在介紹使用Visual C++ 開發基于ORACLE 數據庫應用程序的兩種方法。
2. 使用PRO*C 開發數據庫應用
2.1 PRO*C 工作原理
PRO 系列是ORACLE 公司提供的在第三代高級程序設計語言中嵌入SQL 語句來訪問數據庫的一套預編譯程序,包括PRO*Ada、PRO*C、PRO*COBOL、PRO*Fortran、PRO*Pascal 和PRO*PL/I 六種。程序員用相應的高級語言編寫嵌入SQL 語句的PRO 源程序(若用C 語言則稱為PRO*C 源程序)后運行相應的預編譯程序,把嵌入的SQL 語句轉換為標準的ORACLE 調用并生成目標源程序,即純高級語言格式的源程序,然后就可以將這些源程序加入用戶的程序中調用,其處理過程如下圖。
ORACLE 預編譯程序提供如下功能:
⑴能用六種通用的高級程序設計語言中的任何一種編寫應用程序。
⑵遵循ANSI 標準,在高級語言中嵌入SQL 語句。
⑶可采用動態SQL 方法,讓程序在運行時接受或構造一個有效的SQL 語句。
⑷實現ORACLE 內部數據類型和高級語言數據類型之間的自動轉換。
⑸可通過在應用程序中嵌入PL/SQL 事物處理塊來改進性能。
⑹能在程序行和命令行上指定所需要的預編譯可選項,并可在預編譯的過程中改變它們的值。
⑺能全面檢查嵌入的SQL 數據操縱語句和PL/SQL 塊的文法和語義。
⑻可用SQL*Net 并行存取多個地點的ORACLE 數據庫。
⑼可把數組作為輸入和輸出程序變量使用。
⑽能對應用程序中的代碼段進行條件預編譯。
⑾提供了較強的異常處理功能。
由此可見,通過預編譯程序與其它高級語言的結合,既可以利用SQL 強有力的功能和靈活性為數據庫應用系統的開發提供強有力的手段,又可以充分利用高級語言自身在系統開發方面的優勢,從而提供一個完備的基于ORACLE 數據庫應用程序的開發解決方案。
2.2 在VC 中使用PRO*C
每個PRO*C 源文件一般由程序頭和程序體兩部分組成。程序頭包含宿主變量(SQL 語句中所包含的變量)說明、通訊區定義和C 外部表示符的說明等。程序體一般是由若干函數組成,這些函數內含有SQL 語句(以EXEC SQL 起頭的語句)。
PRO*C 支持的數據類型包括VARCHAR2( 變長字符串)、NUMBER( 二進制數)、INTGER( 有符號整數)、FLOAT( 浮點數)、STRING( 以NULL 結尾的字符串)、VARNUM( 變長二進制數)、LONG( 變長字符串)、VARCHAR( 變長字符串)、ROWID( 二進制值)、DATE( 定長日期/ 時間值)、VARRAW( 變長二進制數據)、RAW( 定長二進制數據) 、LONGRAW( 變長二進制數據)、UNSIGNED( 無符號整數)、LONGVARCHAR( 變長字符串)、LONGVARRAW( 變長二進制數據)、CHAR( 定長字符串)、CHARZ(C 中定長以NULL 結尾的字符串)、MLSLABEL( 變長二進制數據)。
在PRO*C 中不能使用'l' 或'u' 作詞尾或'0x' 作詞頭修飾常量;在SQL 語句中使用單引號來定義字符串,用雙引號來定義特殊的或小寫字符的標識符( 如表名等);SQL 語句中不允許使用C 中的尋址、間接、位邏輯、復合賦值、?=、-、++、%、<<、>> 操作符并且用NOT、AND、OR、= 代替!、&&、||、==。
下面的程序是一個聯結數據庫的PRO*C 源程序例子。
#include < sqlca.h > //聲明SQL通訊區 #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數據庫連接失敗!"); return; }*/ }
在VC 中使用PRO*C 時,先用PRO*C 編寫所需的操作數據庫的子程序,再運行PRO*C 預編譯程序把PRO*C 源程序轉成相應的CPP 源程序,將該程序插入到用戶工程文件中并在需要對插入函數進行調用的模塊中說明函數,然后就可以在此模塊中調用所需的函數。
3. 使用ODBC 中間件訪問數據庫
3.1 ODBC 工作原理
DBC 是Open Database Connect 即開放數據庫互連的簡稱,它是由Microsoft 公司于1991 年提出的一個用于訪問數據庫的統一界面標準,是應用程序和數據庫系統之間的中間件。它通過使用相應應用平臺上和所需數據庫對應的驅動程序與應用程序的交互來實現對數據庫的操作,避免了在應用程序中直接調用與數據庫相關的操作,從而提供了數據庫的獨立性。
ODBC 主要由驅動程序和驅動程序管理器組成。驅動程序是一個用以支持ODBC 函數調用的模塊(在WIN95 下通常是一個DLL),每個驅動程序對應于相應的數據庫,當應用程序從基于一個數據庫系統移植到另一個時,只需更改應用程序中由ODBC 管理程序設定的與相應數據庫系統對應的別名即可。驅動程序管理器(包含在ODBC32.DLL 中)可鏈接到所有ODBC 應用程序中,它負責管理應用程序中ODBC 函數與DLL 中函數的綁定。
ODBC 使用層次的方法來管理數據庫,在數據庫通信結構的每一層,對可能出現依賴數據庫產品自身特性的地方,ODBC 都引入一個公共接口以解決潛在的不一致性,從而很好地解決了基于數據庫系統應用程序的相對獨立性,這也是ODBC 一經推出就獲得巨大成功的重要原因之一。
從結構上分,ODBC 分為單束式和多束式兩類。
⑴單束式驅動程序
單束式驅動程序介于應用程序和數據庫之間,像中介驅動程序一樣數據提供一個統一的數據訪問方式。
當用戶進行數據庫操作時,應用程序傳遞一個ODBC 函數調用給ODBC 驅動程序管理器,由ODBC API 判斷該調用是由它直接處理并將結果返回還是送交驅動程序執行并將結果返回。
由上可見,單束式驅動程序本身是一個數據庫引擎,由它直接可完成對數據庫的操作,盡管該數據庫可能位于網絡的任何地方。
⑵多束式驅動程序
多束式驅動程序負責在數據庫引擎和客戶應用程序之間傳送命令和數據,它本身并不執行數據處理操作而用于遠程操作的網絡通信協議的一個界面。
前端應用程序提出對數據庫處理的請求,該請求轉給ODBC 驅動程序管理器,驅動程序管理器依據請求的情況,就地完成或傳給多束驅動程序,多束式驅動程序將請求翻譯為特定廠家的數據庫通信接口(如Oracle 的SQLNet)所能理解的形式并交于接口去處理,接口把請求經網絡傳送給服務器上的數據引擎,服務器處理完后把結果發回給數據庫通信接口,數據庫接口將結果傳給多束式ODBC 驅動程序,再由驅動程序將結果傳給應用程序。
3.2 在VC 中使用ODBC
Visual C++ 中提供了CDatabase、CRecordset、CRecordView、CDBException 和CFieldExchange 五個類,這些類封裝了ODBC SDK 函數,從而使用戶可以無需了解SDK 函數就可以很方便地操作支持ODBC 的數據庫。
CDatabase 類:封裝了與數據庫建立連接,控制事務的提交和回滾及執行SQL 語句的方法。
CRecordset 類:封裝了大部分操縱數據庫的方法,包括瀏覽、修改記錄,控制游標移動,排序等操作。
CRecordView 類:提供了與recordset 對象相連接的視,可以建立視中的控件與數據庫數據的對應,同時支持移動游標,修改記錄等操作。
CDBException 類:提供了對數據庫操作的異常處理,可以獲得操作異常的相關返回代碼。
CFieldExchange 類:提供了用戶變量與數據庫字段之間的數據交換,如果不需要使用自定義類型,你將不用直接調用該類的函數,MFC Wizard 將自動為程序員建立連接。
4. 兩種方法的比較
綜上所述,使用這兩種方法在Visual C++ 中都可以很方便地開發出基于ORACLE 數據庫的應用程序,同時,這兩種方法又各有其優缺點。ODBC 由于有MFC 強大的類庫支持而使得編程實現非常方便,同時可移植性也很強,在異構的數據庫之間移植也只需更改很少的一部分程序,但是,由ODBC 的實現機制我們可以看到,與PRO*C 相比,應用程序需要經過ODBC 驅動程序管理器和ODBC 驅動程序兩層才能和數據庫通信接口建立聯系,而PRO*C 是直接與通信接口聯系,因此建立在ODBC 上應用程序的執行效率會相對低一些。PRO*C 具有執行效率高,支持嵌入式PL/SQL 塊等ORACLE 自身特有的優點,但正因為有了這些優點,使得用PRO*C 開發出的應用程序無法向異構數據庫平臺移植。 | |