Geçici tabloları veya tablo değişkenlerini kullanarak SQL Server Saklı Yordamları Oracle'a nasıl taşınır?


9

SQL Server saklı yordamları yazmak için yönetim tarafından teşvik C # geliştirici genellikle böyle prosedürler üretmek

create table #t1 (...);
insert into #t1 Select ... from table_a where ...;
insert into #t1 Select ... from table_b where ...;
update #t1 Set ... = ... where ...
Select * from #t1;

Tek ifade oldukça basittir ve bu yöntem onları doğru sonuçlar üretmelerini sağlar.

Çoğu zaman görevim bu prosedürleri Oracle'a taşımaktır.

Aşağıdaki gerçeklerle yüzleşelim.

  • SQL Server'daki farklı geçici tablolara tamamen bağımsızdır ve herhangi bir geçici yapıya sahip olabilir.
  • Oracle global ortak tabloları global nesnelerdir ve hepsi aynı tablo yapısını paylaşır. Herhangi bir yerde kullanılırken bu yapıyı değiştirmek imkansızdır.

Bir Oracle dba'dan öğrendiğim şeylerden biri, mümkün olduğunda geçici tabloların kullanımından kaçınmaktı. SQL sunucusundaki performans bile bu tür değişikliklerden yararlanır.

Ayrı uçları sendikalarla değiştirin

En basit durumda, yukarıdaki gibi bir şeye dönüştürülebilir

select case when ... then ... end, ... from table_a where ...
union
select case when ... then ... end, ... from table_b where ...
Order by ...;

Fonksiyonların kullanımı

Hem skaler fonksiyonlar hem de tablo değerli fonksiyonlar, prosedürünüzü yukarıdaki formun tek bir sorgusuna dönüştürmeye yardımcı olabilir.

Ortak Tablo ifadeleri aka Alt Sorgu Faktoringi

Subquery Factoring, Oracle'ın geçici tablolardan kaçınmak için sunduğu en iyi yöntemdir. Bunu kullanarak SQL Server'ın Oracle'a geçişi oldukça kolaydır. Bu, SQL Server 2005 ve üstünü gerektirir.


Bu değişiklikler SQL Server sürümünü geliştirir ve çoğu durumda geçişi doğrudan yapar. Diğer durumlarda, küresel geçici tablolara başvurmak, geçişi sınırlı bir zamanda yapmayı mümkün kılar, ancak daha az tatmin edicidir.


Oracle'da genel geçici tabloların kullanılmasını önlemenin başka yolları var mı?


3
Böyle bir kodun yordamsal temelli olmayan düşünmeye dayalı bir gösterge olduğunu söyleyeceğim. Ve bunlar tek bir # ile yerel geçici tablolardır. Ben yönetimim ve üretime
girdiğini görürsem

Tamamen katılıyorum
bernd_k

@gbn - Deyimsel PL / SQL deyimsel T-SQL'den biraz daha prosedürel olma eğilimindedir. Temp tabloları, T-SQL'de set op'larda neredeyse her şeyi yapmayı mümkün kılar. PL / SQL, paralel imleç op'larına ve prosedür kodunu optimize etmek için çok daha fazla işleve sahiptir.
ConcernedOfTunbridgeWells

Yanıtlar:


3

Bunu yapmanın bir yolu Nesne Türleri olacaktır , bu durumda tür sizinkiyle benzer olacaktır #t1. Bu yüzden bir yerde tanımlanması gerekecek, ancak küresel olması gerekmeyecek, şema başına veya prosedür başına bile olabilir. İlk olarak, bir tür oluşturabiliriz:

SQL> create or replace type t1_type as object (x int, y int, z int)
  2  /

Type created.

SQL> create or replace type t1 as table of t1_type
  2  /

Type created.

Şimdi bazı örnek veriler ayarlayın:

SQL> create table xy (x int, y int)
  2  /

Table created.

SQL> insert into xy values (1, 2)
  2  /

1 row created.

SQL> insert into xy values (3, 4)
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

Ve bu veriler üzerinde "geçici" türümüzü döndüren bir işlev oluşturun:

SQL> create or replace function fn_t1 return t1 as
  2  v_t1 t1 := t1();       -- empty temporary table (really an array)
  3  v_ix number default 0; -- array index
  4  begin
  5  for r in (select * from xy) loop
  6  v_ix := v_ix + 1;
  7  v_t1.extend;
  8  v_t1(v_ix) := t1_type(r.x, r.y, (r.x + r.y));
  9  end loop;
 10  return v_t1;
 11  end;
 12  /

Function created.

Ve sonunda:

SQL> select * from the (select cast (fn_t1 as t1) from dual)
  2  /

         X          Y          Z
---------- ---------- ----------
         1          2          3
         3          4          7

Gördüğünüz gibi bu oldukça hantal (ve en iyi zamanlarda belirsiz bir özellik olan koleksiyon sözde işlevlerini kullanıyor !), Her zaman söylediğim gibi, DB'den DB'ye taşımak sadece SQL lehçelerindeki sözdizimi ve anahtar kelimelerle ilgili değil , gerçek zorluk farklı temel varsayımlarla gelir (SQL Server durumunda, imleçlerin pahalı olduğu ve kullanımlarının her ne pahasına olursa olsun kaçınıldığı / çalıştığı).


3

Eğer durum seçeneği esnek yeterli değildir sen olabilir toplu toplamak için prosedüründe veri ve dizi (ler) işlemek.

--Setup
CREATE TABLE table_a (c1 Number(2));
CREATE TABLE table_b (c1 Number(2));
INSERT INTO table_a (SELECT rownum FROM dual CONNECT BY rownum<=4);
INSERT INTO table_b (SELECT rownum+5 FROM dual CONNECT BY rownum<=4);

--Example
DECLARE
   Type tNumberArray Is Table Of Number;
   v1 tNumberArray;
BEGIN
   SELECT c1 BULK COLLECT INTO v1 FROM (
      SELECT c1 FROM table_a
      UNION ALL
      SELECT c1 FROM table_b
      );

   For x IN v1.First..v1.Last Loop
      /* Complex manipulation goes here. */
      If (v1(x) <= 3) Then
         v1(x) := v1(x)*10;
      End If;
      DBMS_OUTPUT.PUT_LINE(v1(x));
   End Loop;
END;
/

+1, ancak bu bir sonuç kümesi döndürmez (eğer bir SELECTT-SQL depolanmış proc'ta son şeyse, geri dönüş budur)
Gaius

Bu kod bloğu bir prosedüre dönüştürülmüşse, diziyi döndürebilir veya dizileri imleç olarak açabilir ve imleci geri geçirebilir, hatta bir işlev haline getirebilir ve satırları geri bağlayabilirsiniz. Bunların her biri benzer olacaktır, ancak kullanmanız gereken duruma bağlıdır.
Leigh Riffel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.