原文: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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

