帶參游標,不支持記錄類型%ROWTYPE,不支持數組等,原Oracle用到這些的必須改寫
五、Job的移植
Job是Oracle的定時任務實現的方法,MySQL6中用Event實現,具體語法請參考MySQL手冊。
在MySQL中使用event請注意,默認它是不運行的,您可以
1) 保證MySQL定時任務event scheler運行,需要MySql 5.1.6以上,并且在啟動后執行SET GLOBAL event_scheler = ON;(也可以在初始配置文件比如my.ini中加入event_scheler = ON的參數)
2) 啟用event功能后,每次執行會往MySQL的錯誤日志文件寫一些信息(data目錄下的“主機名.err”文件),導致這個文件越來越大(除非經常做flush log操作)。所以,如果您的event執行很頻繁,可在my.ini中加參數買粉絲nsole=TRUE,這樣執行event的信息就不會寫進來了
六、用戶的移植
Oracle的用戶管理和MySQL下有較大區別,請分別建立用戶,并賦予合適的權限。
七、應用程序的移植
由于語法細節上的差異,導致很多SQL語句需要改寫。筆者記下了所有移植過程中碰到的SQL語句細節差異,這些也是一般項目可能會用到的地方,雖然肯定不全,但也列出來以供參考:
1)Oracle的to_char函數不能再使用,換用如CONCAT(14.3)的形式,為了提高應用程序兼容性,建議手工寫一個
2)Oracle的to_date函數不能再使用,建議手工寫一個添加到MySQL數據庫
3)Oracle的de買粉絲de函數不能再使用,換用SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END 的形式
4)nvl這樣的一些專用函數,MySQL是沒有的,可以把
select nvl(to_char(num),'nothing') from t_equipment轉換成
select case num when num then num else 'nothing' end from t_equipment
5)instr之類的函數,函數名相同,但參數個數不同
6)Oracle的sysdate要寫成sysdate()的形式
7)包的形式已經取消,所以原來以包的方式調用的過程如xx_pack.xxx要寫成xxx()
8)帶進制字符轉數字
Oracle風格:TO_NUMBER(strTmp,'XX') TO_NUMBER(’9’)
MySQL風格:CONV(strTmp,16,10) CONV(’9’,10,10) 如果字符串前后有加減操作,會隱含轉換成數字
9) 不能再有直接調用序列的形式,如果一定需要,可以模擬實現一個
10)日期直接加減的含義不同了,比如Oracle中sysdate + 1 變成了sysdate() + interval 1 day(注意如果寫成sysdate() + 1 語法還是正確的,但含義是錯誤的)
查詢select sysdate() + 1 from al 在MySQL得到比如 20080223153234(= 20080223153233 + 1)的數
而在Oracle中會得到第二天當前時刻。
11) MySQL單純的date類型只是日期不帶時間,DATETIME或TIMESTAMP帶有時間,用DATE_FORMAT函數可以控制顯示形式
12)select 'abc' || 'd' from al 兩個數據執行的結果不同(語法都能通過),MySQL要寫成select 買粉絲ncat('abc' , 'd')的形式
13) Oracle高級功能,如帶有暗示索引的select語句,MySQL是不支持的(語法可以通過)
14)有些MySQL的保留字不能直接用在SQL語句里,要加表名或別名限制,如select RIGHT FROM XX要改成select a.RIGHT FROM XX a
15) Oracle的子查詢可以不起別名,但MySQL是必須的,比如下面的別名aa:
select field1 from (select sysdate() as field1 from al) as aa
16)很多系統表名都是不同的,比如,列出某個表的信息:
select * from tab where TName='T_TEST'改成
select table_name,table_type from information_schema.tables where table_schema = 'user' and table_name=' T_TEST '
17)MySQL下update時不能有本身的子查詢
update T_TEST set Flag = 0 where field1 in
(select distinct b.field1 from T_TEST b where b.flag=1)
18)Oracle下’’和null等價,而MySQL則不然
select 1 from al where '' is null在Oracle下可以取到記錄,在MySQL下不能
al表的使用,substr、trim等函數的主要使用方式和Oracle類似
八、小結和建議
看起來,Oracle移植到MySQL似乎挺麻煩,有沒有一鍵完成的簡單辦法?呵呵,我沒有找到,除非您只使用基本表,只使用基本SQL語句訪問它。當然,建議大家初始設計的時侯,就考慮到多數據庫的支持,權衡一下使用一些高級功能帶來的好處和對可移植性方面帶來的損害,這會大大減少后期移植時面對的問題;另外,在應用架構設計時,也建議使用較好的框架去屏蔽這些差異,比如J2EE的Hibernate框架等。
感謝偉大的Oracle,給我們提供了很多的高級功能,有很多是MySQL沒有的,因此,在移植時你不得不放棄一些非必須的功能,比如,全表cache、物化視圖、函數索引等;如果該功能是必須的,您可能要使用別的方式來實現,或者轉到應用程序層面來考慮。當然,這些功能MySQL今天沒有,不代表明天也沒有,我們可以拭目以待。
由于開源軟件的原因,MySQL的bug或者缺陷有時還會干擾你,請仔細測試和優化您的應用程序,調整MySQL的配置參數,確保它可以運行得和Oracle下一樣好。
(責任編輯:王倩)
第一范式:如果關系模式R的每個關系r的屬性值都是不可分的原子值,那么乘R是第一范式。
例如關系模式R(NAME,ADDRESS,PHONE),如果一個人有兩個電話號碼沒那么在關系中至少要出現兩個元組,一邊存儲這兩個號碼
第二范式:如果關系模式R是1NF,且每個非主屬性完全函數依賴于候選鍵,那么R是第二范式
設關系模式R(WXYZ),主鍵是WX,R上還存在FD X->Z(也就是wx->z是一個局部依賴)此時應把R分成兩個模式:
R1(XZ),主鍵是X;
R2(WXY),主鍵是WX,外鍵是X(REFERENCES R1).利用外間和主見的練級可以從r1和r2重新得到R.
至于你這個題目據下面一個例子:
倉庫(倉庫號,貨物號,庫存量,倉庫地址) 其中倉庫號和貨物號為主鍵--------1NF
轉換為2NF:
庫存(倉庫號,貨物號,庫存量) 庫存號和貨物號是主鍵
倉庫(倉庫號,倉庫地址) 倉庫號是主鍵
為什么會這樣 在1NF中,庫存量完全依賴于倉庫號和貨物號,而倉庫地址部分依賴于倉庫號和貨物號。 怎么弄成2NF 也是按照這個道理轉換的
--需要使用函數,下面是我剛寫的函數
create function getIP
(
@ip varchar(8000),
@idx int
)
returns varchar(3)
as
begin
while @idx>1
begin
if(charindex('.',@ip)=0)
return null
set @ip=substring(@ip,charindex('.',@ip)+1,len(@ip))
set @idx=@idx-1
end
if(charindex('.',@ip)>0)
return substring(@ip,0,charindex('.',@ip))
return @ip
end
--下面是調用:
Declare @ip varchar(15)
set @ip='192.168.0.100'
select dbo.getIP(@ip,1),dbo.getIP(@ip,2),dbo.getIP(@ip,3),dbo.getIP(@ip,4)
查詢結果就是你要的結果。另外如果是 dbo.getIP(@ip,5)的話會返回NULL,避免了錯誤調用。