17 Nisan 2009 Cuma

Oracle NULL

Oracle’a ilk başladığınız zamanlarda eğer önceden farklı veri tabanları ile çalışmışsanız null olan değerler size biraz ilginç gelebilir.
Null hücreler değeri belli olmayan, değeri bilinmeyen hücrelerdir.
Bu nedenle aşağıdaki sorgunun sonucu doğal olarak belirsiz bir değer çıkacaktır, bu da null’a eşittir.
select 5+7+null+9 from dual;

Fakat kullandığımız Oracle Fonksiyonları bu mantıkta çalışmazlar, örneğin SUM() fonksiyonu kullanıldığında null olan değerleri ihmal ederek diğer değerlerin toplamını verir. Benzer şekilde diğer fonksiyonlar da null değerleri ihmal ederler.
Null değerleri daha iyi anlamak için boolean değişkenler ile beraber mantıksal işlemlerlerinin sonucunu gösteren aşağıdaki doğruluk tablosunu inceleyebilirsiniz.
b1 b2| and or
------+--------
1 1| 1 1 ------------ 1: true
1 0| 0 1 ------------ 0: false
1 n| n 1 ------------ n: null value
0 1| 0 1
0 0| 0 0
0 n| 0 n
n 1| n 1
n 0| 0 n
n n| n n

null değerler ile Oracle’da karşılaştırma yapacak ise bilmemiz gereken şey, null değerlerin tipinin string olduğudur, yani null değerler Oracle’da yan yana iki tek tırnak işareti arasındaki ('')karakteri ifade eden STRING('') değeridir. Bu yüzden boş bir stringin uzunluğu(length) 0 değil null dır.
Başka bir özellik olarak Oracle sıralama yaparken null değerleri diğer değerlerden daha büyük olarak kabul eder, sıralama yaptığımız tabloda MAXVALUE hariç bütün null değerler en büyük değerlerdir.

Oracle Table Partitioning

Gittikçe büyüyen ve data yükü artan tablolar üzerinde sorgu çalıştırmak veya tablo bakımına ait diğer işlemleri gerçekleştirmek zamanla çeşitli problemlere sebep olmaktadır. Problemleri ortadan kaldırmanın kullanışlı ve etkili yollarından birisi tabloyu bütünlüğünü koruyacak şekilde parçalara ayırmak ve ilgili işlemleri sadece gerekli olan parçalar üzerinde yapmaktır. Partitioning kavramı bahsedilen bu işlemleri gerçekleştirebileceğimiz bir yapı sunmaktadır, tablonun bütünlüğü korunarak üzerindeki işlemlerin daha hızlı gerçekleştirilebileceği parçalara ayrılır.

Partitioning kavramı üzerinde bahsedilmesi gereken ayrıntılarla devam etmek istiyorum, tablo üzerinde partition oluşturmak tablonun genel bütünlüğünü bozmayacağından tablo üzerinde çalıştırılan sorgularda değişiklik yapmaya gerek yoktur. Bu nedenle işleyen sistemler üzerinde uygun partition metodunu seçerek kullanılan sorguları değiştirmeden partitioning işlemi gerçekleştirilebilir. Aynı zamanda partitioning metoduna bağlı olarak ayrılan her parçanın kendi ismi ile sadece ayrılan parçaya ait işlemler de gerçekleştirilebilir. Parçalar ayrı ayrı drop/truncate edilebilir, üzerlerinde farklı bir index oluşturulabilir. Partitioning in diğer avantajı ise küçük parçalar ile uğraştığından sorgularda çok daha performanslı olmasıdır. Ayrıca partitioning yapılmamış bir tabloya sonradan partitioning yapıldığında tablo üzerinde çalışan sorgu ve DML lerde herhangi bir değişikliğe gerek olmaması bu yapının oldukça esnek olarak kullanılmasını sağlamaktadır.

Partition lara ayrılan bir tabloda herbir satır tek bir parçaya ait olabilir, satırın ait olacağı parçanın belirlenmesi için partition key kullanılır. Partition key null alabilen bir değerden de oluşabilir.

Yukarda bahsettiğim gibi bazı işlemlerin gerçeklenebilmesi tablo üzerindeki partitioning metoduna bağlıdır. Partitioning metodlarını daha yakından inceleyecek olursak:

Oracle tarafından 4 farklı partitioning yöntemi desteklenmektedir:

· Range Partitioning.

· List Partititoning

· Hash Partitioning

· Composite Partitioning

Range Partitioning Metodu

Range metodu ile partition işleminde partition keyi üzerinde belirli aralıklardaki değerlere göre parçalar oluşturulur. Örneğin tablo üzerinde yılların tutulduğu bir alana sahibiz, bu alanı partition key olarak belirleyip yıllara göre parçalar oluşturabilir, artık kullanmayacağımız yılların datalarını direk ilgili partitionu kullanarak drop/truncate edebilir veya belirli bir yıla göre sorgularımızı gerçekleştirebiliriz. Veya illere göre verilerin tutulduğu bir tabloda il kolonu üzerinde partition yapılarak sadece ilgilenilen ilin datası ile işlemler yapılabilir. Partitionda less than ile belirtilen değerden daha küçük olan aralık alınır, MAXVALUE değeri ile ise bir üst sınır belirlenir, belirlenen en büyük değerin dışına çıkan ve null olan değerler bu parça içerisine dahil olacaklardır.

Number tipe gore range partition örneği:

CREATE TABLE emp (
   empno NUMBER(4), 
   ename VARCHAR2(30), 
   sal   NUMBER
) 
PARTITION BY RANGE(empno) (
  partition e1 values less than (1000)     tablespace ts1, 
  partition e2 values less than (2000)     tablespace ts2, 
  partition e3 values less than (MAXVALUE) tablespace ts3
); 

Emp tablosu üzerinde empno keyi kullanılarak bir partition oluşturulmuştur ve 1000 den küçük olan numaralar, 1000-2000 arası olan numaralar ve 2000 den büyük olan numaralar ayrı partitionlarda yer alacaklardır.

Varchar2 string tipe gore partition örneği:

CREATE TABLE emp
( id        NUMBER(5)    PRIMARY KEY,
  name      VARCHAR2(50) NOT NULL,
  phone     VARCHAR2(15),
  email     VARCHAR2(100) )
PARTITION BY RANGE ( name )
        ( 
        PARTITION p1 VALUES LESS THAN ('L')      TABLESPACE ts1,
        PARTITION p2 VALUES LESS THAN (MAXVALUE) TABLESPACE ts2 
        )

Date tipe gore range partitioning örneği:

CREATE TABLE t1 (id NUMBER, c1 DATE)
PARTITION BY RANGE (c1)
  (PARTITION t1p1 VALUES LESS THAN (TO_DATE('2007-11-01', 'YYYY-MM-DD')),
   PARTITION t1p2 VALUES LESS THAN (TO_DATE('2007-12-01', 'YYYY-MM-DD')),
   PARTITION t1p3 VALUES LESS THAN (TO_DATE('2008-01-01', 'YYYY-MM-DD')),
   PARTITION t1p4 VALUES LESS THAN (MAXVALUE)
  );

Hash Partitioning Metodu

Hash partitioning metodu daha çok key olarak range metodundaki gibi bir sınır belirlenemeyecek olan alanlar üzerinde kullanılır, örneğin kimlik numaralarının tutulduğu bir alan üzerinde oluşturulabilir.

Örnekler:

 
create table emp2 (
   empno number(4), 
   ename varchar2(30), 
   sal   number
) 
partition by hash(empno) (
  partition e1 tablespace emp1, 
  partition e2 tablespace emp2, 
  partition e3 tablespace emp3,
  partition e4 tablespace emp4
); 

Emp2 tablosu üzerinde farklı tablespaceler kullanılıp empno alanı key olarak kullanılmış ve partition oluşturulmuştur.

create table emp2 (
   empno number(4), 
   ename varchar2(30), 
   sal   number
) 
PARTITION BY HASH(empno)
PARTITIONS 3
STORE IN (empts1, empts2, empts3);

Hash Partitioning yönteminde partitionlar round robin mantığı ile oluşturulurlar.

List partitioning

List partitioning methodu ile belirlenen bir liste değerini içerek key üzerinden tablo partitionlara ayrılır.

Örnek:

CREATE TABLE myemp_work (

emp# NUMBER PRIMARY KEY,

ename VARCHAR2(30),

salary NUMBER(8,2),

deptno NUMBER)

PARTITION BY LIST (deptno) ( -- Add list partitioning

PARTITION p10 VALUES (10),

PARTITION p20 VALUES (20),

PARTITION p30 VALUES (30,40));

deptno alanı key olarak kullanılmış ve bu alan için belirlenen değerler için tablo içerisinde parçalar oluşturulmuştur.

List partition için ayrıca listede belirtilmeyen veya listede yer almayıp sonradan eklenebilecek olan değerler ve null değerler için DEFAULT VALUE kullanılır.

CREATE TABLE myemp_work (

emp# NUMBER PRIMARY KEY,

ename VARCHAR2(30),

salary NUMBER(8,2),

deptno NUMBER)

PARTITION BY LIST (deptno) ( -- Add list partitioning

PARTITION p10 VALUES (10),

PARTITION p20 VALUES (20),

PARTITION p30 VALUES (30,40)

PARTITION PDEF VALUES(DEFAULT));

Composite Partitioning

Composite partitioning yöntemi diğer kullanılan yöntemlerin beraber kullanılması ile elde edilen bir yöntemdir. Daha önceden üzerinde partitioning oluşturulmuş olan bir tablodaki parçalar üzerindeki alt parçalar da parçalara ayrılarak verinin içeriğine ve kullanım amacına göre daha kullanışlı bir yapı sağlanabilir.

Range-hash ve range-list metodları birlikte kullanılarak yerine göre avantajlı olan özelliklerinden faydalanılabilir.

Örnek range-hash partitioning yapısı oluşturma:

CREATE TABLE orders(
 ord#       NUMBER,
 orderdate  DATE,
 prod#      NUMBER,
 quantity   NUMBER)
PARTITION    BY RANGE(orderdate)
SUBPARTITION BY HASH(prod#) SUBPARTITIONS 4 -- STORE IN(ts1, ts2, ts3, ts4)
( PARTITION q1 VALUES LESS THAN (TO_DATE('01-APR-2009', 'DD-MON-YYYY')),
  PARTITION q2 VALUES LESS THAN (TO_DATE('01-JUL-2009', 'DD-MON-YYYY')),
  PARTITION q3 VALUES LESS THAN (TO_DATE('01-OCT-2009', 'DD-MON-YYYY')),
  PARTITION q4 VALUES LESS THAN (MAXVALUE)
);

Bahsedilen partitioning methodlarından en uygun olanını seçmek verinin tipine, sunuluş şekline göre değişiklik gösterecektir, bu aşamada hepsinin avantajlı olan kısımlarını göz önünde bulundurarak seçim yapmak gerektiğini göz önünde bulundurmalıyız.

Partition işlemleri yaptığımız tablo üzerinde partitionlara ayrılmış kısımlar hakkında detylı bilgilere aşağıdaki sorguyu kullanarak bakabiliriz.

SELECT * FROM dba_tab_partitions WHERE table_name = '';

10 Nisan 2009 Cuma

ORACLE Auto Increment Kolon/Alan Oluşturma

MS-SQL kullanmış olanlar bilirler auto increment kolon oluşturmak iki tıklama kadar kolaydır fakat ORACLE a gelince işler biraz farklı yürüyor, öncelikle tablo üzerinde bir SEQUENCE oluşturmak gerekiyor ve bu SEQUENCE i kullanarak tabloya yapılan işlemler esnasında bir TRIGGER ile bu SEQUENCE içerisindeki next değeri almak gerekiyor.

Önce bir tablo oluşturalım:

SQL> CREATE TABLE test
(id NUMBER PRIMARY KEY,
name VARCHAR2(30));

Daha sonra bir SEQUENCE oluşturalım:

-- increment faktörünü ve başlangıç değerini 1 olarak belirledik.
SQL> CREATE SEQUENCE test_sequence
START WITH 1
INCREMENT BY 1;

Şimdi oluşturduğumuz SEQUENCE i tabloya insert öncesinde kullanabiliriz:

CREATE OR REPLACE TRIGGER test_trigger
BEFORE INSERT
ON test
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT test_sequence.nextval INTO :NEW.ID FROM dual;
END;
/

Trigger i de yarattığımıza göre artık birkaç insert cümlesi ile testimizi yapabiliriz:

-- Burada öemli olan insert edeceğimiz value lar içerisinde id ye yer vermememiz, id değeri zaten auto increment bir değer olduğundan SEQUENCE i kullanarak bir sonraki değerini otomatik olarak alacaktır.

SQL> INSERT INTO test (name) VALUES ('Jon');

1 row created.

SQL> INSERT INTO test (name) VALUES (’Bork’);

1 row created.

SQL> INSERT INTO test (name) VALUES (’Matt’);

1 row created.

Sonuçlara bakarsak id değerinin otomatik değerler aldığını görürüz:

SQL> SELECT * FROM test;

ID NAME
———- ——————————
1 Jon
2 Bork
3 Matt

SEQUENCE in bağımsız olarak commit edildikten sonra update edilmesi sayesinde birden fazla kullanıcının aynı tabloya aynı anda insert etmesi bir sorun oluşturmayacaktır.

ORACLE Bir Şemadaki Bütün Tabloların İçerdiği Kayıt Sayıları

-- ORACLE Bir Şemadaki Bütün Tabloların İçerdiği Kayıt Sayıları

select owner, table_name, num_rows from sys.dba_tables where owner = 'USER_NAME' ORDER BY num_rows desc;

ORACLE Bir Şemadaki Tüm Tabloların Sayısı

-- Bir Şemadaki Tabloların Sayısını

select count(*) from sys.dba_tables where owner = 'USER_NAME' ORDER BY num_rows desc ;

Popüler Yayınlar