ERTELENEMEZ VE BAŞLANGIÇTA ERTELENEBİLİR


92

Ben SQL anahtar kelime hakkında okumak DEFERRABLEiçinde Komple Kitabı - Veritabanı Sistemleri .

İkincisi [DEFERRABLE] varsayılandır ve bir veritabanı değişiklik ifadesi her yürütüldüğünde, değişiklik yabancı anahtar kısıtlamasını ihlal edebilecekse, kısıtlamanın hemen ardından kontrol edildiği anlamına gelir.

Ancak, bir kısıtlama beyan edersek ERTELENEBİLİR edersek, kısıtlamayı kontrol etmeden önce bir işlemin tamamlanmasını bekletme seçeneğimiz vardır.

Biz kelime izleyin ertelenebilir biri tarafından INITIALLY DEFERRED veya INITIALLY IMMEDIATE . İlk durumda, kontrol, her işlem tamamlanmadan hemen önce ertelenecektir. İkinci durumda, kontrol her ifadeden hemen sonra yapılacaktır.

Nasıl NOT DEFERRABLEfarklıdır DEFERRABLE INITIALLY IMMEDIATE? Her iki durumda da, öyle görünüyor ki, her bir ifadeden sonra herhangi bir kısıtlama kontrol edilir.

Yanıtlar:


74

İle DEFERRABLE INITIALLY IMMEDIATE, ihtiyaç duyduğunuzda talep üzerine kısıtlamaları erteleyebilirsiniz.

Bu, normalde kısıtlamaları ifade zamanında kontrol etmek istiyorsanız, ancak örneğin bir toplu iş yükü için kontrolü tamamlama zamanına kadar ertelemek istiyorsanız yararlıdır.

Bununla birlikte, kısıtlamaların nasıl erteleneceği sözdizimi, çeşitli DBMS için farklıdır.

İle NOT DEFERRABLEasla taahhüt zamanına kadar kontrolü erteleyemezsiniz.


1
@romkyns: DEFERRABLEtasarımcının kısıtlamayı ertelemenin değerli veya gerekli bir eylem olduğunu belirtir. Bu, veritabanı kısıtlamalarının büyük çoğunluğu için geçerli değildir ve hepsini DEFERRABLEbu yararlı ayrımı kaybedecek şekilde etiketlemek .
birgün

4
@onedayBir meslektaşım o zamandan beri geçerli bir sebebe işaret ettiğinde, aslında: herhangi bir işlemin herhangi bir noktasında ertelenemez kısıtlamalara güvenebilirsiniz, ancak ertelenebilir olanlar yalnızca işlemin başlangıcında kesinlikle gözlemlenir.
Roman Starkov

@RomanStarkov Bir de performans meselesi. NOT DEFERRABLEgenellikle en hızlısıdır.
Teejay

50

Diğer (doğru) cevapların yanı sıra , PostgreSQL'den bahsederken şunu belirtmek gerekir:

  • DEFERRABLE DEĞİL ile her satır ekleme / güncelleme zamanında kontrol edilir

  • ile deferrable (şu anda HEMEN ) tüm satırları ekleme / güncelleme sonunda kontrol edilir

  • ile deferrable (şu anda ERTELENEN ) tüm satırları işlemin sonunda kontrol edilir

Dolayısıyla , ERTELENEBİLİR kısıtlamasının HEMEN olarak ayarlandığında ERTELENEMEZ bir DEĞİL gibi davrandığını söylemek doğru değildir .


Bu farkı ayrıntılı olarak inceleyelim:

CREATE TABLE example(
    row integer NOT NULL,
    col integer NOT NULL,
    UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE
);

INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3);

UPDATE example SET row = row + 1, col = col + 1;

SELECT * FROM example;

Bu doğru çıktı:

çıktı

Ancak ERTELENEBİLİR BAŞLANGIÇ HEMEN komutunu kaldırırsak,

HATA: yinelenen anahtar değeri "example_row_col_key" benzersiz kısıtlamasını ihlal ediyor DETAIL: Anahtar ("satır", sütun) = (2, 2) zaten var. ********** Hata **********

HATA: yinelenen anahtar değeri benzersiz "example_row_col_key" kısıtlamasını ihlal ediyor SQL durumu: 23505 Ayrıntı: Anahtar ("satır", sütun) = (2, 2) zaten var.


EK (12 Ekim 2017)

Bu davranış gerçekten burada , "Uyumluluk" bölümünde belgelenmiştir :

Ayrıca, PostgreSQL ertelenemez benzersizlik kısıtlamalarını, standardın önerdiği gibi ifadenin sonunda değil, anında kontrol eder.


İlginç. Bana öyle geliyor ki, "ERTELENEMEZ" davranışını "HEMEN" davranışa tercih etmek için temelde bir neden yok ve Postgres'in daha bağışlayıcı olması ve "HEMEN" gibi davranmaması için Postgres'in daha bağışlayıcı olması mantıklı. Bir UPDATE ifadesindeki satırların güncellenme sırası bildiğim kadarıyla belgelenmemiş veya belirtilmemiştir, bu nedenle bu orta ifade kısıtlama kontrolünün davranışı en azından kısmen belirtilmemiş mi? Neden göremiyorum kimse bu davranışı isteyeyim - ama belki de görmeyi hayal yoksun olduğunu bunun için makul bir kullanım durumu var.
Mark Amery

1
Evet, temelde tercih etmenin tek nedeni NOT DEFERRABLEhızdır ( buraya bakın , Ertelenmemiş Benzersizlik Kısıtlamaları bölümü , "Bunun anlık benzersizlik kontrolünden önemli ölçüde daha yavaş olabileceğini unutmayın" ).
Teejay

Ayrıca, DEFERRABLEkısıtlamaya diğer tablolarda yabancı anahtarlar olarak başvurulamaz ( buraya bakın , Parametreler , "Başvurulan sütunlar, başvurulan tablodaki ertelenemez benzersiz veya birincil anahtar kısıtlamasının sütunları olmalıdır" ).
Teejay

1
Dolayısıyla, genel bir kural olarak, kısıtlama kontrol edildiğinde iş mantığı için gerçekten önemli değilse, daha NOT DEFERRABLEiyi performans gösterdiği için varsayılan olarak kullanmalı mıyım?
dvtan

1
ORM'mizde şimdi aşağıdaki kuralları kullanıyoruz: 1) kısıtlama bir PK ise, NOT DEFERRABLE2) en az bir FK kısıtlamaya başvuruyorsa, NOT DEFERRABLE3) diğer durumlarda da kullanıyoruz DEFERRABLE INITIALLY IMMEDIATE. Bu, bu kısıtlamaların performansını biraz düşürebilir, ancak kullandığımız diğer DBMS (Oracle, SqlServer) ile maksimum uyumluluk sağlar. PK ve FK bir sorun değil çünkü değerlerini asla güncellemiyoruz (ki bu DB'ler için iyi bir programlama alışkanlığı olduğunu düşünüyorum).
Teejay

29

Erteleyebilmenin bariz olmasının yanı sıra, fark aslında performanstır. Bir performans cezası olmasaydı, ertelenebilir veya ertelenemez seçme seçeneğine sahip olmaya gerek kalmazdı - tüm kısıtlamalar ertelenebilirdi.

Performans cezası, verilerin nasıl kısıtlandığı bilgisi verildiğinde veritabanının gerçekleştirebileceği optimizasyonlarla ilgilidir. Örneğin, Oracle'da benzersiz bir kısıtlamayı desteklemek için oluşturulan dizin, geçici olarak kopyalara izin verilmesi gerektiğinden kısıtlama ertelenebilirse benzersiz bir dizin olamaz. Bununla birlikte, kısıtlama ertelenemezse, dizin benzersiz olabilir.


7

Partiye çok geç kaldım ancak şunu eklemek istedim - Aralık 2018 itibariyle - bildiğim sadece iki veritabanı (daha fazla olabilir) bu standart SQL özelliğinin bir düzeyde uygulanmasını sağlıyor :

Database    NOT DEFERRABLE  DEFERRABLE           DEFERRABLE 
                            INITIALLY IMMEDIATE  INITIALLY DEFERRED
----------  --------------  -------------------  ------------------
Oracle      N/A *1          Yes (default)        Yes
PostgreSQL  Yes (default)   Yes                  Yes
DB2         -               -                    -
SQL Server  -               -                    -
MySQL       -               -                    -
MariaDB     -               -                    -
SAP Sybase  -               -                    -
HyperSQL    -               -                    -
H2          -               -                    -
Derby       -               -                    -

* 1 Oracle 12c NOT DEFERRABLE kısıtlama durumunu kabul etse de , aslında onu görmezden gelir ve olarak çalışmasını sağlar DEFERRABLE INITIALLY IMMEDIATE.

Gördüğünüz gibi, Oracle ilk türü ( NOT DEFERRABLE) uygulamıyor ve bu nedenle Oracle kullanan geliştiricilerin (bu durumda OP) kafaları karışabilir ve ilk iki türün eşdeğer olduğunu düşünebilir.

İlginçtir ki Oracle ve PostgreSQL'in farklı bir varsayılan türü vardır. Belki performans etkileri vardır.


4

ERTELENEMEZ - kısıtlama denetimini değiştiremezsiniz, oracle bunu her ifadeden sonra kontrol eder (yani ifadeyi girdikten hemen sonra).

ERTELENEBİLİR BAŞLANGIÇ HEMEN - oracle her ifadeden sonra kısıtlamayı kontrol eder. ANCAK, bunu her işlemden sonra değiştirebilirsiniz (yani taahhütten sonra):

set constraint pk_tab1 deferred;
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.