2016-12-23 64 views
6

INSERT INTO xxx (col) SELECT ... numaralı telefonu çalıştırırken MySQL 5.6 InnoDb ile NOT NULL adlı bir yabancı anahtarı yok sayıyorum. Ekleme, diğer biçimlerde eklerken kısıtlama zorlanır. Yabancı anahtar kontrolünü etkindir ve sql_mode = STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTIONMySQL Insert Select NOT NULL Constraint'ı Zorlama Yok

İşte bir örnek:

CREATE TABLE Test_Parent 
(
    id BIGINT(18) UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT, 
    dummy VARCHAR(255) 
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci 
    COMMENT 'Test parent table'; 

CREATE TABLE Test_Child 
(
    id BIGINT(18) unsigned PRIMARY KEY NOT NULL AUTO_INCREMENT, 
    fid BIGINT UNSIGNED NOT NULL, 
    FOREIGN KEY Fk_Test_Parent_01(fid) REFERENCES Test_Parent(id) 
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COLLATE = utf8_unicode_ci 
    COMMENT 'Test child table'; 

INSERT INTO Test_Parent(dummy) 
VALUES ('test'); 

## Here's where the FK constraint should be enforced but isn't ## 
INSERT INTO Test_Child(fid) 
SELECT id 
    FROM Test_Parent 
WHERE dummy = 'missing value'; 

1 row affected in 5ms 

## Running an insert with a different format, the constraint is enforced ## 
INSERT INTO Test_Child(fid) 
VALUES (null); 
Column 'fid' cannot be null 

## Running this format, the foreign key is also enforced ## 
INSERT INTO Test_Child(id, fid) 
VALUES (123, (SELECT id FROM Test_Parent WHERE dummy = 'missing value')); 
Column 'fid' cannot be null 

MySQL 3 insert tabloların dışında 2 yabancı anahtar zorunlu kılar neden anlamıyorum. Herhangi bir fikir?

+1

çünkü 'WERE' deyimi eşleşmediğinden, INSERT ... SELECT' aslında herhangi bir satır ekinde sonuçlanmaz. Eğer her iki tablodan “SELECT *” ise, “Test_Child” satırında hiçbir satır görmüyorum ... http: //sqlfiddle.com/#! 9/7413e0/1 –

+0

Gerçek verileriniz ve kullanım durumunuz önemli ölçüde farklı değilse Test bizim için ayarladı. –

+0

Doğru - 1 satır eklendiğini bildiriyor, ancak tabloya hiçbir şey eklenmedi. Bu senaryoda "NULL değil" kısıtının uygulanmasını beklerim. Bunun yerine, istisna yutulurmuş gibi. – adam

cevap

1

Müşterinizden gelen bir yanıltıcı 1 row affected in 5ms mesajınız burada karışıklık kaynağı olabilir. Yorum mesajında, IntelliJ'in bu mesajı bildirdiğinden bahsetmiştiniz, ancak iyi tanımlanmış test tablolarınızı hem MySQL 5.6.35 hem de 5.7.16-ubuntu'da çalıştırdım ve her iki sürümde söz konusu beyan 0 etkilenen satırları rapor ettiler:

mysql > INSERT INTO Test_Child(fid) 
    -> SELECT id 
    ->  FROM Test_Parent 
    -> WHERE dummy = 'missing value'; 
Query OK, 0 rows affected (0.00 sec) 
Records: 0 Duplicates: 0 Warnings: 0 

Yanıltıcı etkilenen satırlar iletisine bakarak, burada gerçekten olan şey, INSERT...SELECT deyiminizin SELECT bölümünün hiçbir satırla eşleşmemesidir ve bu nedenle MySQL herhangi bir satır ekleme girişiminde bulunmaz. Bu nedenle, yabancı anahtar kısıtlama ihlali yoktu.

INSERT INTO...SELECT biçiminin daha sonra örnekten biraz farklıdır

: bu durumda, sayısal hazır 123 güçler, bir satır eklenecek çünkü ...

INSERT INTO Test_Child(id, fid) 
VALUES (123, (SELECT id FROM Test_Parent WHERE dummy = 'missing value')); 

ve bir null ile eşleştirilmiş alt seçimden döndürülen değer. Böylece, null eklemeye ve bir kısıtlama ihlaline neden oluyor.

Eğer boş değer içeren bir satır dönmek için INSERT...SELECT zorlarsanız, nedeniyle bir kısıtlama ihlali başarısız yapabiliriz: Buna "etkilenen 1 satır" bir misreported görüyoruz acaba

INSERT INTO Test_Child (fid) 
-- Return a literal NULL row... 
SELECT NULL as id FROM Test_Parent 
-- Column fid cannot be null