2011-09-06 12 views
7

Oracleのテーブルを更新しようとしていますが、何か問題があります。私は自分のコードをMySQLから移植しています.MySQLが許すいくつかのコマンドはOracleではサポートされていません。ここでOracle 11GのLIMIT/OFFSET

はMySQLのコードは次のとおりです。

update table1 t1 set c5 = (select ContractID from table2 t2 where t1.assetid = 
t2.assetid and t1.lastdate >= t2.lastdate and t1.firstdate= t2.firstdate 
order by lastdate asc limit 1 offset 4); 

サブクエリがlastdateでソート、のContractIDのリストを返し、私は特定のものにしたい、それゆえの限界1は、Xコマンドを相殺しました。

問題は次のとおりです。 Oracleでは、「制限」または「オフセット」コマンドはサポートされていません。 rownumとネストされたクエリを使用した制限問題に対する回避策がありますが、Oracle 11GパーサーはUPDATEコマンドでそれらを好きではありません。

私は更新コマンド内ではなく、オフセットではなく、制限を必要とする前に同様の問題が発生しました。それはここで解決された:MySQL to Oracle Syntax Error (Limit/Offset/Update)

Florin Ghitaが分析関数を使って見つけた回避策があります。

update table1 alf 
    set nextcontractid = 
     (SELECT min(contractid) keep (dense_rank first order by lasttradedate asc) 
     FROM table1copy alf2 
     WHERE alf2.assetid  = alf.assetid 
     AND alf2.lasttradedate > alf.lasttradedate 
    ) 
    where alf.complete = 0 

この回避策は、私が(DENSE_RANKコマンドでASCまたはDESCを使用して)上または下のエントリを取得することができますが、私は第二を望んでいたかどうかは、オフセットコマンドのプロキシを見つけることができないのです3行目。

私が試みた別の解決策は、ネストされたクエリを使用しました。最初のものはrownumコマンドを使って最初の5行を得て、逆順に並べ、最後の4行をMINUSしました。この解決方法は、Oracleパーサーがネストされたクエリーの1つの中で参照される最も外側のコマンドのテーブルへの参照を理解しなかったために失敗しました。

(私は前に持っていたのと同じ問題:MySQL to Oracle Syntax Error (Limit/Offset/Update)

私はすでにネストされたクエリによってそれを行うことができますような課題は、制限を使用してOracleでSELECTステートメントを実行して相殺するだけではありません。問題は、文が構文的に正しいにもかかわらず、Oracleパーサーが文をデコードできないため、select文を更新文で使用できるようにすることです。これまでは、ネストされたクエリ(およびGoogle)が失敗しました。

他に誰も同じような問題があったのですか?

+1

は(table2のt2以降のContractIDを選択するには、12cにアップグレードする場合、あなたは=更新TABLE1 t1のセットC5 'のような何かを行うことができるかもしれませんここでt1.assetid = t2.assetidとt1.lastdate> = t2.lastdateとt1.firstdate = t2.firstdateorder by lastdate asc offset 4次の1行だけを取得); – beldaz

+0

Oracle 12cR1(またはそれ以上):http://stackoverflow.com/a/26051830/1461424 – Krumia

答えて

0

は、私は、これは、単一のSQL文でなんとかする必要があります感じて、これまでのところ、相関サブクエリの必要性および分析機能のいくつかの並べ替えの必要性の組み合わせが持つ本来の答えではなく、生きた

を削除しました私が試したすべてを失敗させた。

ここで私はあなたがやりたいだろうと思い、手続き方法です:

DECLARE 
    CURSOR t IS 
    SELECT LEAD(contractid,4) OVER (PARTITION BY assetid ORDER BY lasttradedate ASC) lead_contractid 
    FROM table1 
    FOR UPDATE; 
BEGIN 
    FOR r IN t LOOP 
    UPDATE table1 SET nextcontractid = r.lead_contractid 
     WHERE CURRENT OF t; 
    END LOOP; 
END; 
+0

Nope。ネストされたクエリは、私が以前に言及した正確な問題を持っています。一番内側のクエリは、一番外側のクエリで指定されていても、ALFの内容を理解しません。 SQLエラー:ORA-00904: "ALF"。"ASSETID":無効な識別子 – Brian

+0

@Brian - 申し訳ありませんが、もちろんあなたは正しいです。私は実際にそれを実行するまで、常にその問題を忘れているようです。 –

+0

私はコードが何をしているのか正確には分かりませんが、あなたが示した概念を使って解決策を考え出しました。 (LEAD関数とストアドプロシージャの使用) 基本的には、インデックスとしてrownumberを使用して、テーブルの各エントリを反復処理するストアドプロシージャを使用しました。 assetid =その行のassetidを検索し、リード関数を使用して次のコントラクトを取得します。 私は、ソリューションのjistはストアドプロシージャを使用することだと思います。 – Brian