oracleデータベース移行sql server 2008

7300 ワード

ヘッドは私に今のプロジェクトデータベースをoracle 10 gからsql server 2008に移行させて、後で必要とするためにしましょう.データベースは370枚のテーブル、70のビュー、30以上の関数、十数個のストレージプロセスで、私は2週間近くやって、効率が低いので、次はこの2週間で出会った問題をまとめます.
以前やったことがないので、インターネットで何かツールがあるかなどを探していましたが、結局2つの方法しか見つかりませんでした.1つはマイクロソフトのツールSSMAで、1つはsql server管理ツールが持っているインポート機能です.
SSMAについて(后で确かにこのツールを使って、使うのはとても简単で、具体的な方法は自分で调べます)、上で1つの头が痛い问题に出会って、oracleを接続して、図のようです
その中でserver name私は長い間やっていたので、たくさんやってみたが何なのか分からなかった.oracleに登録したときのDatebaseと関係があると思っていた.
後でネットで調べたら、oracleでselect*from v$instanceを検索して、結果のHOST_NAMEはこのserver nameで、sid(データベースの一意のラベル)はoracleをインストールする時デフォルトはorclで、もしあなたがインストールする時に修正したら、oracleのインストールディレクトリの下で、D:oracleproduct10.2.0db_1dbs、ファイル名はSPFILEORCLなどです.ORA、それではorcl、つまりファイル名は「SPFILE*****.ORA」で、その中の「****」はSIDで、残りのいくつかは記入しやすいです.次にSSMA接続sql serverを図のように
ここで辺のserver nameはsql server管理ツールにログインしたときのサーバ名です.これはSSMAの最初の問題です.2つ目の問題は、oracleテーブルのnumberタイプのデータをfloat(53)、300枚以上のテーブルに変換することです.あまりにもあっさりしています.私たちのデータベースのnumberの大部分はint型なので(SSMA、float(53)が最も保険的なタイプであるわけではありません)、正直に自分で回転しましょう.他のビュー、ストレージ、関数に間違いがあります.マイクロソフトのこれはまだ知能的ではないようです.
やはり悔しいです.他の方法を探してみると、sql server管理ツールが持っているインポート機能を使って、右クリックデータベース->タスク->データをインポートする人がいることに気づきました.これも使いにくくて、具体的にはあまり言わないで、最後にやっと難しい決定をして、自分で手を出して、服をいっぱい食べました.
一、回転表
まずpl/sql Developerでこの表の建表sqlを見て、それから建表文をコピーして、私はすべての表のsqlを1つのファイルの中に持って行って、便利に一回実行して表をすべて生成しました.このテーブルに外部キー、インデックスがある場合は、管理せずに、外部キーインデックスを作成した文を別のファイルにコピーし、テーブルを作成してから、外部キーインデックスを作成した文を実行すればいいです.回転テーブルの問題は大きくありません.いくつかのデータ型の変換(numberタイプに注意する必要があります)です.以下のようにします.
Oracleデータ型SQL Serverデータ型代替BFILE VARRBINARY(MAX)はBLOB VARBINARY(MAX)はCHAR([1-2000])CHAR([1-2000])はCLOB VARCHAR(MAX)Yes DATE DATETIME FLOAT FLOAT No FLOAT([1-53])FLOAT([1−53]No FLOAT([54−126])FLOAT No INT NUMERIC(38)INTERVAL DATETIMEですLONG VARCHAR(MAX)ですLONG RAW IMAGE Yes NCHAR([1-1000])NCHAR([1-1000])No NCLEBNVARCHAR(MAX)NUMBER FLOATがNUMBER([1-38])NUMERIC([1-38])であるかNUMBER([0-38],[1-38])NUMERIC([0-38],[1-38])がNVARCHR 2([1−2000]NVARCHAR([1−2000])No RAW([1−2000])VARBINARY([1−2000])No REAL FLOAT No ROWID CHAR(18)No TIMESTAMP DATETIMEはUROWID CHAR(18)No VARCHAR 2([1-4000])VARCHAR([1-4000])であるはい
二、私が二番目に回ったのはビューで、後で証明して、ビューは二番目に好転した東で、下はビューの中で出会った問題と注意しなければならないところです.
    1.oracleにselectがある場合...from dualの文は、sql serverでfrom dualを削除すればいいです.
    2.両者の関数については、基本的にはhttp://www.cnblogs.com/wuchaocug/archive/2011/05/27/2059490.htmlを使用して変換を比較します.
    3.sql serverにwm_がありませんconcat関数(フィールド内の文字列を接続する)は、代わりに自分で関数を書く必要があります.参考にしてください.
SELECT  USUID ,
        RESUME = STUFF(( SELECT   ',' + (StartDate+'-'+EndDate+' ' +CropName+''+Duty)
                       FROM     tbWorkResume t
                       WHERE    t.USUID = tbWorkResume.USUID
                     FOR
                       XML PATH('')
                     ), 1, 1, '')
FROM    tbWorkResume
GROUP BY USUID
または
select userid,STUFF((select ','+JOBNAME from tbjoborder j,TBUSERJOB u
							  where  j.joid= u.JOID and u.USERID=uj.USERID
							  for xml path('')
							  ),1,1,'') jobname from tbuserjob uj
				group by userid

    4.エラー:TOPまたはFOR XMLが別途指定されていない限り、ORDER BY句はビュー、インライン関数、派生テーブル、サブクエリ、共通テーブル式では無効です.select文の後にtop 100 percentを加えればいいです.
    5.oracleのstart with...connect byツリークエリー構文sql serverはありません.ここではwith asで置き換えます(http://blog.csdn.net/key_the_one/article/details/7222128より明確に書かれています).
with node AS ( select organid  FROM tborgan 
				 WHERE organid IN (SELECT FOREIGNKEYID as organid FROM tbTPUser a WHERE SELECTMODE=1)
				 UNION ALL SELECT bb.organid
				 FROM tborgan bb inner join node no ON no.organid = bb.organfatherid )
				 --           
				 select * from node 
ここで注意する必要がありますが、クエリの結果が他のクエリのサブ条件となる場合、上のsql文は括弧で包むことはできません.解決策は、ビュー(connと仮定)をもう1つ書き込み、SELECT ORGANID from connで呼び出すことです.
    6.カスタム関数を呼び出す可能性があります.私は彼を放っておいて、関数を回してから、後でこれらのビューを生成します.
    7.SSMA回転のビューはまあまあです.手間を省いてコピーできると思いますが、コピーする前に見なければなりません.いくつかのものも手動で回転しなければなりません.コピーして実行すれば、間違いを報告しないかもしれませんが、一部のものは明らかに間違っています.例えば、SSMAは
Trunc(months_between(SysDate,f.born)/12) UserAge
から
sysdb.ssma_oracle.trunc(sysdb.ssma_oracle.months_between(sysdatetime(), f.BORN) / 12, DEFAULT) AS UserAge
実行時にはエラーは報告されません.
三、カスタム関数の変換、これはあまり好転しません(もちろん関数が簡単であれば、かなり好転します)が、感覚的に言えば、注意できるところもあまり多くありません.
    1.カスタム関数ではbegin tryとbegin catchはサポートされていません.if@@error<>0(上の文が正しく実行されていない場合)で置き換えることができます.
    2.ifとelse、else ifの中身はbegin endで包んだほうがいいです.
    3.oracleはtableタイプを返すことをサポートしていません.一般的にはパイプタイプpipelinedで返します.変換するとsql serverはtableタイプを直接返すことができますが、定義するときは、ネット上で直接このように書かれている人がいます.
create function test()
returns table
as
begin
	return select * from userTable
end
go
ですが、実行時に「BEGIN」付近に文法エラーがあります.これでtableを定義します.
create function test()
returns @Table table(userid int,username varchar(10))
as
begin
	insert into @Table select userid,username from userTable
	return
end
go

  4.sql serverがカーソルを返す問題は、まだ解決していないので、できたらまたここで更新しましょう.
  5.oracleのcharIndex()メソッドには4番目のパラメータがあります.何度目の出現を意味します.sql serverこのメソッドには4番目のパラメータがないので、もう1つのメソッドを書かなければなりません.次は私が書いたものです.完璧ではないかもしれません.
create function dbo.myCharIndex
(
	@partString varchar(max),
	@fullString varchar(max),
	@startIndex int,
	@time int
)
returns int
as
begin
	declare 
		@tempIndex int,
		@tempString varchar(max)
	set @tempIndex = 0
	if(@time < 1)
		return 0
	if(@time = 1)
		return charindex(@partString,@fullString,@startIndex)
	if(@time > 1)
	begin
		set @tempString = subString(@fullString,@startIndex,len(@fullString))
		if(len(@tempString)=0)
		return 0
		while @time >= 1
			begin
				if(@tempIndex+1 > len(@fullString))
						return 0
				else
					begin
						set @tempIndex = charindex(@partString,@tempString,@tempIndex+1)
						if(@tempIndex = 0)
							return 0
						else
							set @time = @time - 1
					end
			end
		return charindex(@partString,@fullString,@startIndex+@tempIndex-1)
	end
	return 0
end
go
   
四、ストレージプロセスの変換
    1.oracleはビューの更新をサポートします(使用/*+*/)
update (
select  /*+ BYPASS_UJVC */  a.tpid,nvl(a.cid,0) cid,a.cexamgrade,c.exscore,a.egid tpegid,c.egid
from tbtpcourseresult a 
inner join tbtestpaper b on a.tpid=b.relakey and a.cid=nvl(b.relakey2,0) and b.papermode=16
inner join tbexamineegrade c on b.tpid=c.tpid and a.userid=c.userid ) 
set cexamgrade=exscore,tpegid=egid;
sql serverはこのようにするしかありません(このように正しく回転することを知りませんか?どの大侠が答えをあげます)
update tbtpcourseresult set cexamgrade=c.exscore,egid = c.egid from
tbtpcourseresult a 
inner join tbtestpaper b on a.tpid=b.relakey and a.cid=isnull(b.relakey2,0) and b.papermode=16
inner join tbexamineegrade c on b.tpid=c.tpid and a.userid=c.userid

    2.rownumについては、以下の代わりに使用できます(sql serverは2005バージョン以上でなければなりません).インターネットで検索する方法もたくさんあります.
select * from (select Row_Number() over     
(Order by UserId) as RowId ,* from UserInfo) U 
where U.RowId between 10 and 20

    3.sql serverは次の方法でトランザクションを制御します.
BEGIN
IF @@TRANCOUNT > 0
     COMMIT WORK 
IF @@TRANCOUNT > 0
     ROLLBACK WORK 
END
oracleトランザクションを次の方法で制御
COMMIT;
EXCEPTION
  WHEN OTHERS THEN
  ROLLBACK;

五、他は続きましょう