Bir Tecrübeli Newb Oracle Sorunlar

9 Cevap php

Platformu için yeni, ancak ilişkisel veritabanlarında (genel olarak MySQL, MS SQL Server, Postgres, vb) için yeni değil başkası için bazı Oracle gotchas nelerdir.

Ben arıyorum şeylerin tür iki örnek

  1. Birçok ilişkisel veritabanı ürünleri sizin için bir auto_increment anahtarını oluşturarak kolu. Oracle, elle tetik oluşturmak, sonra sırası oluşturmanız gerekir değil

  2. SQL Developer arayüzü ile veri eklerken, elle veri işlemek zorunda

Bu platformu I'll bu varsayımsal deneyimli newb kullanarak olacaktır olduğu gibi PHP ile ilgili FRİKİKLERİNDEN için bonus puan.

9 Cevap

Note: I'm explaining only the gotchas here, i. e. situations when Oracle behaves not as other systems do. Oracle has numerous benefits over other RDBMS's, but they are not the topic of the post.

  • Sen SELECT FROM olmadan yapamam.

    SELECT  1
    

    başarısız olur, yapmanız gerekir:

    SELECT  1
    FROM    dual
    
  • Boş dize ve NULL aynı şeydir.

    SELECT  *
    FROM    dual
    WHERE   '' = ''
    

    hiçbir şey döndürür.

  • Ne TOP ne LIMIT vardır. Sen WHERE fıkrasında sonuçlarınızı sınırlayabilir:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    ROWNUM önce değerlendirilecek beri bir alt sorgu kullanarak tam olarak bu şekilde, ORDER BY.

  • Sen yuva birden fazla düzey derin ilişkili alt sorgusu olamaz. Bu bir başarısız olur:

    SELECT  (
            SELECT  *
            FROM    (
                    SELECT  dummy
                    FROM    dual di
                    WHERE   di.dummy = do.dummy
                    ORDER BY
                            dummy
                    )
            WHERE   rownum = 1
            )
    FROM    dual do
    

    Bu bir sorundur.

  • NULL değerleri endeksli değildir. Bu sorgu sipariş için bir dizin kullanmak olmaz:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    col olarak işaretlenmiş sürece NOT NULL.

    O NULL values bu değil columns, endeksli değil var daha unutmayın. Bir null sütun üzerinde bir dizin oluşturabilirsiniz, ve non-NULL değerleri dizin içine alacak.

    Sorgu koşul NULL değerleri belki onu tatmin edebilir varsayar Ancak, endeks kullanılmayacaktır.

    Yukarıdaki örnekte tüm değer (s NULL dahil) iade etmek istiyorum. Sonra indeksi dolayısıyla, bunları alamıyor, non-NULL değerleri bilmiyor.

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    Ama bu sorgu endeksi kullanacağız:

    SELECT  *
    FROM    (
            SELECT  *
            FROM    mytable
            WHERE   col IS NOT NULL
            ORDER BY
                    col
            )
    WHERE   rownum < 10
    

    , Non-NULL değerleri hiç koşulu tatmin olamaz çünkü.

  • Varsayılan olarak, NULL s ilk değil, son sıralanmıştır (PostgreSQL gibi, ancak MySQL ve SQL Server aksine)

    Bu sorgu:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id
    

    döndürür

    id
    ---
    1
    NULL
    

    SQL Server ve MySQL, bu kullanmak gibi sıralamak için:

    SELECT  *
    FROM    (
            SELECT  1 AS id
            FROM    dual
            UNION ALL
            SELECT  NULL AS id
            FROM    dual
            ) q
    ORDER BY
            id NULLS FIRST
    

    Ikincisi alt sorgunun dışında kullanılmadığı sürece bu rownum sırasını keser unutmayın (yukarıda açıklandığı gibi)

  • "MYTABLE" ve "mytable" (çift tırnak önemli) farklı nesnelerdir.

    SELECT  *
    FROM    mytable -- wihout quotes
    

    eski, ikincisi değil seçim yapacak. Eski yoksa, sorgu başarısız olur.

    CREATE TABLE mytable
    

    oluşturur "MYTABLE" değil, "mytable".

  • Oracle, tüm örtülü kilitleri (DML faaliyetlerinden o sonuç) satır düzeyi ve kışkırtılmış asla. Bu işlem tarafından etkilenen hiçbir satır örtülü kilitli edilebilir.

    Yazarlar okuyucular (ve tersi) blok asla.

    Bütün tablo kilitlemek için, açık bir LOCK TABLE bildiri yayınlamaları gerekir.

    Satır kilitleri datapages saklanır.

  • Oracle, "CLUSTERED endeksleri" hayır vardır içinde, "index-organize tablolar var." Varsayılan olarak, tablo (SQL Server farklı ve MySQL InnoDB) ile düzenlenmiştir yığın bulunmaktadır.

    Oracle dünyasında, bir "kümelenmiş depolama" (birkaç tablodan) ortak anahtarını paylaşmak satırlar da Veri Sayfası paylaşmak, böylece birkaç tablo düzenleme anlamına gelir.

    Tek DataPage süper hızlı bu anahtarı üzerinde birleştirmeler yapar birden fazla tablodan birden çok satır barındırır.

1 alışkanlık iş SEÇİN, yerine çift çıkışlı 1 seçerim.

Eğer hiyerarşik verilerle çalışıyorsanız, harika bağlamak.

MySQL gibi bir grup birleştirme yoktur. Bir grup birleştirme toplam işlevi istiyorsanız, kendi yazmak zorunda. İşte benim uygulamasıdır:

drop type T_GROUP_CONCAT;

create or replace type GROUP_CONCAT_PARAM as object
(
  val varchar2(255),
  separator varchar2(10),
  numToConcat NUMBER,
  MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt  return VARCHAR2
);

--map function needed for disctinct in select clauses
CREATE OR REPLACE TYPE BODY GROUP_CONCAT_PARAM IS
    MAP MEMBER FUNCTION GROUP_CONCAT_PARAM_ToInt return VARCHAR2 is 
      begin 
        return val; 
      end; 

end;


/

CREATE OR REPLACE TYPE T_GROUP_CONCAT 
AS OBJECT (

runningConcat VARCHAR2(5000),
runningCount NUMBER,

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN       GROUP_CONCAT_PARAM
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateTerminate
  ( self             IN   T_GROUP_CONCAT,
    returnValue  OUT VARCHAR2,
    flags           IN   NUMBER
  ) RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge
  (self  IN OUT T_GROUP_CONCAT,
   ctx2 IN      T_GROUP_CONCAT
  ) RETURN NUMBER

);
/

CREATE OR REPLACE TYPE BODY T_GROUP_CONCAT AS

STATIC FUNCTION ODCIAggregateInitialize
  ( actx IN OUT T_GROUP_CONCAT
  ) RETURN NUMBER IS 
  BEGIN
    IF actx IS NULL THEN
      actx := T_GROUP_CONCAT ('', 0);
    ELSE
      actx.runningConcat := '';
      actx.runningCount := 0;
    END IF;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateIterate
  ( self  IN OUT T_GROUP_CONCAT,
    val   IN     GROUP_CONCAT_PARAM
  ) RETURN NUMBER IS
  BEGIN
    if self.runningCount = 0 then
        self.runningConcat := val.val;
    elsif self.runningCount < val.numToConcat then
        self.runningConcat := self.runningConcat || val.separator || val.val;
    end if;
    self.runningCount := self.runningCount + 1;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateTerminate
  ( self        IN  T_GROUP_CONCAT,
    ReturnValue OUT VARCHAR2,
    flags       IN  NUMBER
  ) RETURN NUMBER IS
  BEGIN
    returnValue := self.runningConcat;
    RETURN ODCIConst.Success;
  END;

MEMBER FUNCTION ODCIAggregateMerge
  (self IN OUT T_GROUP_CONCAT,
   ctx2 IN     T_GROUP_CONCAT
  ) RETURN NUMBER IS
  BEGIN
    self.runningConcat := self.runningConcat || ',' || ctx2.runningConcat;
    self.runningCount := self.runningCount + ctx2.runningCount;
    RETURN ODCIConst.Success;
  END;

END;
/

CREATE OR REPLACE FUNCTION GROUP_CONCAT
( x GROUP_CONCAT_PARAM
) RETURN VARCHAR2
--PARALLEL_ENABLE
AGGREGATE USING T_GROUP_CONCAT;
/

Kullanmak için:

sometable TBL dan | GROUP_CONCAT (2) 'GROUP_CONCAT_PARAM (tbl.someColumn) seçin

One comment: Eğer Sybase / SQL Server KIMLIK sütunu davranışını kopyalayan hakkında sert değilsen, dizileri kullanmak için bir tetikleyici oluşturmak zorunda değilsiniz. Ben sadece, örneğin gerçek insert tablolara, doğrudan sırasını kullanmak için daha yararlı buluyorum

INSERT
  INTO MyTable
     ( KeyCol
     , Name
     , Value
     )
SELECT Seq_MyTable.NextVal
     , 'some name'
     , 123
  FROM dual;

Sen tetikleyici yürütme yükü hakkında endişelenmenize gerek yoktur, ve sıra değerleri (örneğin başka bir şemanın veri taşırken olarak) atanan olma konusunda endişelenmenize gerek kalmadan tabloya satır ekleme ile uğraşmak esnekliğe sahip. Sen KIMLIK özelliği zor ya da imkansız hale getirir ya veri ve diğer tekniklerin aralıkları eklemek için diziden de ön değerleri seçin can.

Steve'in Yorumlarınız için +1. Ben insanların Oracle üzerinde yetişmiş için objectr adları etrafında çift tırnak kullanmayın doğaldır, ve bunu iğrenç olduğunu düşünüyorum. Bazen diğerleri farklı uygulamalara sahip olduğunu unutmayın.

Null değerleri ile tamamen dolu olabilir bir satır kümesi herhangi bir sütun etrafında nvl (kolon) kullanmayı unutmayın. Aksi takdirde, sütun satır eksik olacaktır.

Bu tamamen eksik, doğru!

Örnek:

SELECT nvl(employeeName,'Archie'), nvl(employeeSpouse,'Edith') FROM Employee

Bu, hem de tüm değerler null bile, size kümesi içinde iki sütun elde garanti edecek. Sen sadece 'Archie' ve 'Edith' değerleri bir demet göreceksiniz. Eğer nvl () kullanmak istemiyorsanız, potansiyel tek bir sütun ya da ne geri alabilir. Bu yakaladım-doğu kısmı kod geliştirme ortamında iyi çalıştırmak ve hatta QA geçebilir olduğunu, ancak üretim aldığında, values tablo değişebilir {[(1)] } sonuç!

Bir null sütun seçerek her Yani, kısacası, nvl () kullandığınızdan emin olun.

Ben dava SQL Server daha şema nesneleri ve verileri duyarlı olmak daha Oracle veritabanları içine çalıştırmak gibi görünüyor.

Temporary tables

Oluşturabilir ve dizin onları normal tablolar gibi ama her oturum / işlem sadece kendi verilerini görür. Bu MS SQL farklıdır.

Global variables

Bunlar referans olarak geçirilir. Bu parametre olarak bir prosedüre global bir değişken geçmek ve prosedür içinde küresel değişkeni değiştirirseniz, parametre değeri de değişecek demektir. Değil çok popüler bir yöntem olsa.

Triggers

Çok yeni sürümleri kadar benzer tetikleyiciler ateş hangi bir yol belirlemek için hiçbir yolu yoktu. Eğer gerçekten "HER SATIR İÇİN GÜNCELLEME ÖNCE" olan bakım ise ilk önce bir tetikleyici tüm koymak.