2012-03-26 24 views
11

Şu anda başka bir sqlite veritabanından (ekleyemiyorum) bir tablo alabildiğim ve her bir sütuna fazladan veri ekleyebileceğim bir sqlite veritabanı oluşturmaya çalışıyorum.INSERT VEYA DEĞİŞTİR + yabancı anahtar AÇIK DELETE CASCADE çok iyi çalışıyor

Bununla hiçbir INSERT OR UPDATE geldi orada olduğundan:
İki tablolarına veri bölme düşünüyordum ve sonrasında onlara katılmak yüzden sadece değişti bir tablo yerine her şeyi içine bütün ithalat dökümü ve ekstra yönetebilir Bu veriler ayrı ayrı ithalatta değişmez.

ilk tablo muhtemelen bir senkronizasyon zaman damgası ekleriz (local_id her şey sadece uzaktan veritabanı ayna olacağını yanında

local_id | remote_id | base_data1 | base_data2 | ... 
---------+-----------+------------+------------+---- 

gibi görünecektir (haydi base_data diyelim) ama bunun bir önemi yok şimdi).

ikinci tablo benzer ama remote_id kümesi vardır ederim yabancı anahtar

remote_id | extra_data1 | extra_data2 | ... 
----------+-------------+-------------+---- 

    CREATE TABLE extra_data (
     remote_id INTEGER 
      REFERENCES base_data(remote_id) 
      ON DELETE CASCADE ON UPDATE CASCADE 
      DEFERRABLE INITIALLY DEFERRED, 
     extra_data1 TEXT, 
     extra_data2 TEXT, 
     /* etc */ 
    ) 

Şimdi benim fikrimdi I içe veritabanı veya hiçbir senkron zaman damgası vardır ve ben karşılaştırmak zorunda kalacak basitçe INSERT OR REPLACE INTO base_data ... değerleri nedeniyle UPDATE neye ihtiyacım olduğunu öğrenmek için gereken her şey/INSERT.

Ama burada sorun yatıyor: INSERT OR REPLACE aslında bir INSERT ardından DELETE ve silme kısmı ben kısıtlamasını DEFERRED yaparak engelleyebilir düşünce yabancı anahtar ON DELETE tetikler. Bir işlemde INSERT OR REPLACE'u kaydırıyorsam çalışmaz. Ekstra verilerimi her zaman silme işleminden sonra aynı yabancı anahtar var olsa da.

INSERT OR REPLACE tamamlanıncaya kadar ON DELETE durdurmak için kullanılabilir mi? Belki bazı özel işlem modu/pragma? Sadece DELETE deyimi ile tetiklenir

CREATE TRIGGER on_delete_trigger 
    AFTER DELETE ON base_data 
    BEGIN 
     DELETE FROM extra_data WHERE extra_data.remote_id=OLD.remote_id; 
    END; 

O tetik ve bugüne kadar benim sorunu çözmek olmalıdır: Ben gibi bir tetikleyici tarafından ON DELETE CASCADE parçayı değiştirin eğer

cevap

3

Bu işi gibi görünüyor. gerekçe

(söz konusu OP tarafından sağlanan cevap) jmathew tarafından

Ek bilgiler, documentation:

REPLACE çakışma çözümleme stratejisi sınırlamayı yerine getirmek amacıyla satırları siler

, tetikleme tetikleyicileri etkinleştirildiyse ve yalnızca yinelemeli tetikleyiciler etkinse. (Eğer örneğimizde yaptığımız gibi) yalnızca başvurulan tablodaki birincil anahtar üzerinde tek bir yabancı anahtar ilişkisi varsayarsak

0

, bu benim için oldukça ağrısız çözüm olduğunu kanıtladı.

Sadece yabancı anahtar denetimlerini devre dışı bırakın, değiştirme sorgusunu çalıştırın ve sonra yabancı anahtarları yeniden etkinleştirin.

Değiştirme anahtarı, yabancı anahtarlar devre dışıyken çalışan tek sorguysa, yabancı anahtarların sıfırlanmayacağından emin olabilirsiniz. Yeni bir satır ekliyorsanız, henüz hiçbir şeye bağlanma şansınız olmaz ve bir satırı değiştirirseniz, var olan satır kaldırılmayacak veya birincil anahtarı sorgu tarafından değiştirilmeyecek ve bu nedenle kısıtlamaya devam edecektir. Yabancı anahtarlar tekrar etkinleştirildiğinde.

PRAGMA foreign_keys=OFF; 
INSERT OR REPLACE ...; 
PRAGMA foreign_keys=ON; 
:

SQLLite kodu şöyle görünür

İlgili konular