2011-09-06 25 views
7

Oracle'da bir tabloyu güncellemeye çalışıyorum ve bazı zorluklarla karşılaşıyorum. Kodumu MySQL'ten alıyorum ve MySQL'in izin verdiği bazı komutlar Oracle'da desteklenmiyor.Oracle'da LIMIT/OFFSET 11G

İşte MySQL kodudur:

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); 

alt sorgu ContractIDS listesini döndürür, lastdate göre sıralanır ve ben sadece belirli bir dolayısıyla sınırı 1 ofset X komutunu istiyorum.

Sorun şu şekildedir. Oracle "limit" veya "offset" komutlarını desteklemez. Rownum ve iç içe geçmiş sorguları kullanarak sınır sorununda geçici çözümler vardır, ancak Oracle 11G ayrıştırıcısı bunları UPDATE komutunda beğenmez.

Bir güncelleştirme komutunda bir sınıra gereksinim duyduğumdan önce benzer bir sorunla karşılaştım, ancak bir sapma değil. Burada çözüldü: Florin Ghita'nın analitik işlevler kullanarak bulduğu bir geçici çözüm var.

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 

Bu geçici çözüm beni (DENSE_RANK komutu ASC veya DESC kullanarak) üst veya alt girişini ulaşmasını sağlar, ancak ikinci istemek ya da ben, ofset komut için bir proxy bulmak mümkün değilim üçüncü sıra.

Denediğim başka bir çözüm, iç içe geçmiş bir sorgu kullandı. İlk rownum komutunu kullanarak ilk 5 satırı aldılar, onları karşı yöne emretti, son dört satırdan MINUS-ed. Bu çözüm, Oracle ayrıştırıcısının iç içe geçmiş sorgulardan birinde başvurulan en dıştaki komuttaki bir tabloya yaptığı başvurudan anlamadığı için başarısız oldu.

(Aynı sorun daha önce sahip olduğu gibi: MySQL to Oracle Syntax Error (Limit/Offset/Update)) Zaten yapabilirim olarak meydan okuma, bir sınırı ile oracle seçkin bir deyimi çalıştırın ve ofset basitçe değil

olduğu iç içe sorgular aracılığıyla. Buradaki zorluk, bir deyim sözdizimsel olarak doğru olsa bile, Oracle ayrıştırıcısının bunları çözemediği için, bir deyim içinde çalışma ifadesinin seçilmesini sağlamaktır. Şimdiye kadar, iç içe geçmiş sorgular (ve Google) beni başarısız oldu.

Başkası da benzer sorunları yaşıyor mu? Yaşatılabilir değil

+1

, sen = (tablo2 t2 ContractID seçmek güncelleme tablo1 t1 seti c5 'Böyle bir şey yapmak mümkün olabilir: Burada

Ne istediğini yapacağını düşünüyorum usul yöntemidir t1.assetid = t2.assetid ve t1.lastdate> = t2.lastdate ve t1.firstdate = t2.firstdate sonuncu asc ofsetiyle sıralama 4 sonraki yalnızca 1 satır getirme); ' – beldaz

+0

İlgili ve muhtemelen yararlıysa Oracle 12cR1 (veya daha yüksek): http://stackoverflow.com/a/26051830/1461424 – Krumia

cevap

0

Silinen orijinal cevap

Bunun tek bir SQL deyiminde yapılabilir olmalıdır hissediyorum ama şimdiye kadar bir ilişkili alt sorgu ihtiyacı ve analitik fonksiyonun çeşit ihtiyacı kombinasyonu vardır başarısız olduğum her şeyi yaptım. Eğer 12c yükseltirseniz

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. iç içe geçmiş sorguları, daha önce bahsettiğim kesin problemi var. En içteki sorgu, en dış sorguda belirtilse bile ALF'nin ne olduğunu anlamıyor. SQL Hatası: ORA-00904: "ALF"."ASSETID": geçersiz tanımlayıcı – Brian

+0

@Brian - üzgünüm, tabiki haklısın. Aslında bu konuya girene kadar bu sorunu unutuyorum. –

+0

Kodun tam olarak ne olduğundan emin değilim, ancak gösterdiğiniz kavramları kullanarak bir çözüm buldum. (LEAD işlevi ve saklı yordam kullanarak) Temel olarak, tablodaki her girdiden yinelenen bir saklı yordam kullandım ve dizin sayısını dizin olarak kullanarak. Bu, assetid'i arar = o satırın varlısı sipariş eder ve bir sonraki sözleşmeyi lead işlevini kullanarak alır. Sanırım çözümün bir saklı yordamı kullanmaktır. – Brian

İlgili konular