2011年1月11日 星期二

Oracle migrate to MySQL

一、從Oracle移植到MySQL主要有六個方面的內容需要移植,一是表Table,包括表結構和數據,二是觸發器Trigger,三是存儲過程Procedure,函數function和包Package,四是任務Job ,五是用戶等其他方面的移植,六是具體應用程序通過SQL語句訪問時的細節差異克服。筆者用來移植測試的數據庫是:Oracle 9i ,MySQL 6.0,Windows 2000環境。

二、經過映射轉換,比如number會轉換為double,date轉換為timestamp等,請小心處理日期字段的默認值等,表的主鍵,表的索引(Oracle的位圖索引會被轉成BTree索引,另外表和字段的註釋會丟失)等信息。需要特別注意的是,Oracle的自增字段的處理。提供字段自增屬性。
三、觸發器的移植首先,MySQL在6.0以後才支持觸發器!觸發器的移植沒有現成工具,因為兩者之間的語法差異較大,您只能通過手工對照著原來的邏輯一個一個添加。
四、存儲過程,函數和程序包的移植程序包是Oracle用來組織邏輯功能的一個Object,MySQL不支持,因此需要將包裡的存儲過程﹑函數等全部放到該數據庫公有過程和函數里面。

五、Job的移植Job是Oracle的定時任務實現的方法,MySQL6中用Event實現,具體語法請參考MySQL手冊。

六、用戶的移植Oracle的用戶管理和MySQL下有較大區別,請分別建立用戶,並賦予合適的權限。

七、應用程序的移植由於語法細節上的差異,導致很多SQL語句需要改寫。筆者記下了所有移植過程中碰到的SQL語句細節差異,列出來以供參考:
1)Oracle的to_char函數不能再使用,換用如CONCAT(14.3)的形式,為了提高應用程序兼容性,建議手工寫一個
2)Oracle的to_date函數不能再使用,建議手工寫一個添加到MySQL數據庫
eg:
to_char(sysdate,'yyyy-mm-dd')-->date_format(sysdate(),'%Y-%m-%d');
to_date(sysdate,'yyyy-mm-dd')-->STR_TO_DATE(sysdate(),'%Y-%m-%d');
to_char(add_months(to_date ('20000101','yyyymmdd'),1),'yyyy-mm-dd')-->date_add('2000-01-01',interval 1 month);

3)Oracle的decode函數不能再使用,換用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 dual 在MySQL得到比如20080223153234(= 20080223153233 + 1)的數而在Oracle中會得到第二天當前時刻。
11) MySQL單純的date類型只是日期不帶時間,DATETIME或TIMESTAMP帶有時間,用DATE_FORMAT函數可以控制顯示形式
12)select 'abc' || 'd' from dual 兩個數據執行的結果不同(語法都能通過),MySQL要寫成select concat('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 dual) 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 dual where '' is null在Oracle下可以取到記錄,在MySQL下不能dual表的使用,substr、trim等函數的主要使用方式和Oracle類似

八、小結和建議看起來,Oracle移植到MySQL似乎挺麻煩,有沒有一鍵完成的簡單辦法?呵呵,我沒有找到,除非您只使用基本表,只使用基本SQL語句訪問它。

source: http://shshy39.javaeye.com/blog/342512

2011年1月6日 星期四

ORA-00031: session marked for kill 處理Oracle中殺不掉的鎖

一些ORACLE中的進程被殺掉後,狀態被置為"killed",但是鎖定的資源很長時間不釋放,有時實在沒辦法,只好重啟數據庫。現在提供一種方法解決這種問題,那就是在ORACLE中殺不掉的,在OS一級再殺。

1.下面的語句用來查詢哪些對像被鎖:

select object_name,machine,s.sid,s.serial#
from v$locked_object l,dba_objects o ,v$session s
where l.object_id = o.object_id and l.session_id=s.sid;
2.下面的語句用來殺死一個進程:
alter system kill session '24,111'; (其中24,111分別是上面查詢出的sid,serial#)
【注】以上兩步,可以通過Oracle的管理控制台來執行。
3.如果利用上面的命令殺死一個進程後,進程狀態被置為"killed",但是鎖定的資源很長時間沒有被釋放,那麼可以在os一級再殺死相應的進程(線程),首先執行下面的語句獲得進程(線程)號:
select p.spid, osuser, s.program
from v$session s,v$process p
where s.paddr=p.addr and s.sid=24 (24是上面的sid)
4.在OS上殺死這個進程(線程):
1)在unix上,用root身份執行命令:
#kill -9 12345(即第3步查詢出的spid)
2)在windows(unix也適用)用orakill殺死線程,orakill是oracle提供的一個可執行命令,語法為:
orakill sid thread
其中:
sid:表示要殺死的進程屬於的實例名
thread:是要殺掉的線程號,即第3步查詢出的spid。
例:c:>orakill orcl 12345

ORA-00031: session marked for kill

Cause: The session specified in an ALTER SYSTEM KILL SESSION command cannot be killed immediately (because it is rolling back or blocked on a network operation), but it has been marked for kill. This means it will be killed as soon as possible after its current uninterruptible operation is done.
Action: No action is required for the session to be killed, but further executions of the ALTER SYSTEM KILL SESSION command on this session may cause the session to be killed sooner.

kill -9 12345



source: http://unixboy.javaeye.com/blog/168346
http://www.oracle-base.com/articles/misc/KillingOracleSessions.php

2011年1月5日 星期三

T-SQL While Loop

declare @Part_Id int
declare @Category_Id int
declare @Desc varchar(50)
create table PART (Part_Id int, Category_Id int, Description varchar(50))
set @Part_Id = 0
set @Category_Id = 0
while @Part_Id < 2
begin
set @Part_Id = @Part_Id + 1
while @Category_Id < 3
begin
set @Category_Id = @Category_Id + 1
set @Desc = 'Part_Id is ' + cast(@Part_Id as char(1)) +
' Category_Id ' + cast(@Category_Id as char(1))
insert into PART values(@Part_Id,
@Category_Id,
@Desc )
end
set @Category_Id = 0
end
select * from PART
drop table PART
Here is the output from the SELECT statement at the bottom of this nested WHILE loop example.

Part_Id Category_Id Description
----------- ----------- -----------------------------------------
1 1 Part_Id is 1 Category_Id 1
1 2 Part_Id is 1 Category_Id 2
1 3 Part_Id is 1 Category_Id 3
2 1 Part_Id is 2 Category_Id 1
2 2 Part_Id is 2 Category_Id 2
2 3 Part_Id is 2 Category_Id 3

2011年1月4日 星期二

SQL Server日期函數CONVERT範例

MS SQL Server中文版的預設日期datetime格式是yyyy-mm-dd hh:mm:ss.mmm

例如:
select getdate()

2011-01-05 11:06:08.177

SQL Server常用到日期格式轉換方式如下:

select CONVERT(varchar, getdate(), 120 )
2004-09-12 11:06:08

select replace(replace(replace(CONVERT(varchar, getdate(), 120 ),’-',”),’ ‘,”),’:',”)
20040912110608

select CONVERT(varchar(12) , getdate(), 111 )
2004/09/12



Text Convert to Datetime
SELECT convert(datetime, '09/02/2010', 103)
here 103->英國/法國標準

source: http://technet.microsoft.com/zh-tw/library/ms187928.aspx