原文:http://www.cnblogs.com/xcj26/p/3452628.html
接觸編程以來,在數據存儲方面一直用的MS SQL。Oracle這名字對我來說是如此的熟悉,但是對其內容卻很陌生,最近公司的一個項目用起了Oracle,所以也開始高調的用起了Oracle。 在沒有接觸Oracle之前,聽很多人都說Oracle的語法與MS SQL差不多,我在朋友圈里也幫著吹噓這個觀點。告訴朋友們,Oralce與MSSQL差不多,確實,貌似一看CRUD幾乎沒區別,但是當你慢慢深入了解 Oracle的時候,你會發現這個觀點有點愚蠢。
我們先來說個很常見的開發案例,有一張Account表,有兩個字段分別為AccountID, AccountName,其中AccountID為主鍵,往這個表中插入數據,以主鍵為唯一標識,表中存在這條記錄則修改,不存在則添加。
一:在MS SQL中
首先創建一個Account表,為了簡單,我們都以nvarchar(50)作為字段類型。具體代碼如下:
if object_id (N ' Account ' ,N ' U ' ) is not null drop table Account create table Account ( AccountID nvarchar ( 50 ) primary key not null , AccountName nvarchar ( 50 ) )
接下來我們要做的事就是往這個表中插入數據
if not exists ( select * from Account where AccountID = ' 1 ' ) insert into Account(AccountID,AccountName) values ( ' 1 ' , ' Sam Xiao ' ) else update Account set AccountName = ' 肖建 ' where AccountID = ' 1 '
這種代碼,我們在SQL中是寫的如此自然和熟練,但是你在Oracle中,你用這種方式來寫,你會遇上一些麻煩。那現在我們在Oracle中來演示如何完成這樣的需求。
二:在Oracle中
? 首先是創建表有著細微的區別,判斷一個表是否存在,習慣了MS SQL的OBJECT_ID('對象表','對象類型')的童鞋們,你們是不是想到Oracle中也應該有這樣的功能呢?遺憾了,Oracle中沒有此類 函數來判斷一個表是否存在,那就只能通過委婉的方式來實現,MS SQL中有類似于 Select Name From SysObjects Where XType='U'這樣的數據庫表,那對應的Oracle中就有了select? * from user_tables,通過查詢系統表,判斷這個表在數據庫中是否存在,如果存在就刪除,然后再創建。
declare num number ; begin select count ( 1 ) into num from user_tables where table_name = ' ACCOUNT ' ; if num > 0 then dbms_output.put_line( ' 存在! ' ); execute immediate ' drop table ACCOUNT ' ; end if ; execute immediate ' create table Account ( AccountID nvarchar2(50) primary key, AccountName nvarchar2(50) ) ' ; dbms_output.put_line( ' 成功創建表! ' ); end ;
與MS SQL創建一個表對比,是不是還是有一些顯微的差異呢?答案當然是肯定的。
這個演示是前奏,現在來開始我們今天的主題,在 Oracle中,表創建成功了,現在我要往這個表中插入數據,如果新插入的數據在表中存在則修改,不存在則插入,我在網上一搜,驚奇的發現Oracle中 的exists()函數是判斷兩個數據集合的交集是否存在,與MS SQL有一定的區別。這樣的對比雖然會顯的不專業,但是我還是有對比和發表自己觀點自由。于是我在網上瘋狂的搜索Oracle在這個問題上的解決方案,總 結了以下幾種方案,以供大家選擇:
1:隱式游標法 SQL%NOTFOUND?? SQL%FOUND
SQL%NOTFOUND 是SQL中的一個隱式游標,在增刪查改的時候自動打開,如果有至少有一條記錄受影響,都會返回false,這就就巧妙的構思出了第一種解決方案:
begin update account set AccountName = ' 修改-a ' where AccountID = ' 5 ' ; IF SQL % NOTFOUND THEN insert into account(AccountID,AccountName) values ( ' 5 ' , ' 添加-b ' ); END IF ; end ;
先根據唯一ID到數據表中修改一條記錄,如果這條記錄在表中存在,則修改,并且SQL%NOTFOUND返回false。如果修改的記錄不存在,SQL%NOTFOUND返回true,并且執行插入語句。
2:異常法 DUP_VAL_ON_INDEX
當Oracle語句執行時,發生了異常exception進行處理
begin insert into account(AccountID,AccountName) values ( ' 6 ' , ' 添加-b ' ); exception when DUP_VAL_ON_INDEX then begin update account set AccountName = ' 修改-b ' where AccountID = ' 6 ' ; end ; end ;
當往表中插入一條數據,因為表中有主鍵約束,如果插入的數據在表中已經存在,則會拋出異常,在異常拋出后進行修改。
3:虛擬表法? dual
dual是一個虛擬表,用來構成select的語法規則,oracle保證dual里面永遠只有一條記錄。
declare t_count number ; begin select count ( * ) into t_count from dual where exists ( select 1 from account where AccountID = ' 11 ' ); if t_count < 1 then dbms_output.put_line( ' 添加 ' ); insert into account(AccountID,AccountName) values ( ' 11 ' , ' 添加-11 ' ); else dbms_output.put_line( ' 修改 ' ); update account set AccountName = ' 修改-11 ' where AccountID = ' 11 ' ; end if ; end ;
先聲明一個變量t_count,表dual表的值賦給t_count,如果這個值小于1,表示記錄不存在,進行插入操作,反之,存在就進行修改操作。
4:no_data_found法
先查找要插入的記錄是否存在,存在則修改,不存在則插入。具體的實現如下:
declare t_cols number ; begin select AccountName into t_cols from account where AccountID = ' 8 ' ; exception when no_data_found then begin -- dbms_output.put_line('添加'); insert into account(AccountID,AccountName) values ( ' 8 ' , ' 添加-8 ' ); end ; when others then begin -- dbms_output.put_line('修改'); update account set AccountName = ' 修改-8 ' where AccountID = ' 8 ' ; end ; end ;
5:merge法
先來看一下merge的語法,
MERGE INTO table_name alias1 USING ( table | view | sub_query) alias2 ON ( join condition) WHEN MATCHED THEN UPDATE table_name SET col1 = col_val1 WHEN NOT MATCHED THEN INSERT (column_list) VALUES (column_values);
看了merge的語法后,依葫蘆畫瓢對于我這種抄襲的人來說已經不是什么難事了。?
merge into Account t1 using ( select ' 3 ' AccountID, ' 肖文博 ' AccountName from dual) t2 on (t1.AccountID = t2.AccountID) when matched then update set t1.AccountName = t2.AccountName when not matched then insert values (t2.AccountID, t2.AccountName); commit ;
至此介紹了五種方法來解決我提出的問題。問題是小,但是已經牽涉了Oracle的好幾個知識點。最后你與MS SQL相比,在用法上還是有很大的差異。至此,仁者見仁智者見智。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
