MySQL Koşullu Ekleme


99

Koşullu INSERT oluşturmakta zorlanıyorum

Örnek kimliğinin benzersiz olduğu sütunlara (örnek, kullanıcı, öğe) sahip x_table var. Yalnızca kullanıcının belirli bir öğeye sahip olmaması durumunda yeni bir satır eklemek istiyorum.

Örneğin örnek eklemeye çalışmak = 919191 kullanıcı = 123 öğe = 456

Insert into x_table (instance, user, item) values (919191, 123, 456) 
    ONLY IF there are no rows where user=123 and item=456 

Doğru yöndeki herhangi bir yardım veya rehberlik çok takdir edilecektir.

Yanıtlar:


116

DBMS'niz, bir ekleme yürütürken hangi tablo arasından seçim yapacağınız konusunda sınırlamalar getirmiyorsa, şunu deneyin:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE NOT EXISTS (SELECT * FROM x_table
                             WHERE user = 123 
                               AND item = 456)

Bu ise, dual(mysql şimdi, Oracle başlangıçta bulunan çok) yalnızca bir satır içeren bir tablodur. Mantık, SELECT ifadesinin gerekli değerlerle tek bir veri satırı oluşturmasıdır, ancak yalnızca değerler önceden bulunamadığında.

Alternatif olarak, MERGE ifadesine bakın.


1
dualBu durumda elden önce oluşturulması gerekiyor mu yoksa sadece sorgunun kullanımı için sorgu tarafından oluşturulan bir tür özel "geçici" tablo mu?
itsmequinn

8
dualZaten sahip değilseniz, onu oluşturmanız gerekir. CREATE TABLE dual ( dummy CHAR(1) DEFAULT 'x' NOT NULL CHECK (dummy = 'x') PRIMARY KEY ); INSERT INTO dual VALUES('x'); REVOKE ALL ON dual FROM PUBLIC; GRANT SELECT ON dual TO PUBLIC;
Jonathan Leffler

Teşekkürler bunu bilmek harika
itsmequinn

11
MySQL'de var olmak için gerçekten 'dual' adında bir tabloya sahip olmanıza gerek olmadığını unutmayın: bu, içinden herhangi bir şey seçmek için kullanılabilecek özel bir tablo adıdır.
Christopher Schultz

3
MySQL, "ikili" kavramına "saygı duyar", ancak gerçekte mevcut değildir. Örneğin, SELECT COUNT(*) FROM dualher zaman alırsanız 1ve SELECT 'foo' FROM dualher zaman alırsanız foo. Ama yapamazsın SELECT * FROM dualve yapamazsın DESCRIBE dualya da onun gibi bir şey. Kontrol etmedim, ancak aynı zamanda izinleri de iptal edebileceğinizi sanmıyorum dual. Bu yüzden beklediğiniz gibi çalıştığını belirtmeye değer ... çalışmadığı zamanlar hariç;)
Christopher Schultz

52

Ayrıca INSERT IGNOREbenzersiz bir dizininiz (kullanıcı, öğe) olduğunda bir satırı güncellemek veya eklemek yerine eki sessizce yok sayan seçeneği de kullanabilirsiniz .

Sorgu şöyle görünecek:

INSERT IGNORE INTO x_table(instance, user, item) VALUES (919191, 123, 456)

Benzersiz dizini ile ekleyebilirsiniz CREATE UNIQUE INDEX user_item ON x_table (user, item).


2
MySQL dokümantasyonu başına INSERT IGNORE, REPLACE ... INSERT IGNORE: eski satırları koruyun. DEĞİŞTİR: yeni satırları koruyun. Her ikisi de benzersiz anahtarlarla çalışır.
Paul Kenjora

Şimdiye kadarki en iyi cevap
jmojico

30

Hiç böyle bir şey denedin mi?

INSERT INTO x_table
SELECT 919191 as instance, 123 as user, 456 as item
FROM x_table
WHERE (user=123 and item=456)
HAVING COUNT(*) = 0;

Oh evet ! tek bir SELECT ifadesiyle akıllı ve güzel bir çözüm
java acm

Güzel. Bu, kabul edilen cevabın bana görünmediği ilk denemede postgresql için çalışıyor.
mightypile

10

A ile UNIQUE(user, item)şunları yapın:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=123

user=123Bit sözdizimini eşleştirmek için bir "hayır-op" dir ON DUPLICATEçiftleri varken aslında hiçbir şey yapmadan maddesi.


1
Bir Benzersiz (kullanıcı, öğe) ayarlayamıyorum çünkü aynı kullanıcı ve öğeye sahip birden çok örnek olabilir ... bu eklemeyi yaptığım zaman değil.
Bilinmeyen

3

Benzersiz bir sınırlama ayarlamak istemiyorsanız, bu bir cazibe gibi çalışır:

INSERT INTO `table` (`column1`, `column2`) SELECT 'value1', 'value2' FROM `table` WHERE `column1` = 'value1' AND `column2` = 'value2' HAVING COUNT(`column1`) = 0

Umarım yardımcı olur !


2

İstediğin şey INSERT INTO table (...) SELECT ... WHERE .... adlı MySQL 5.6 kılavuzu .

Senin durumunda:

INSERT INTO x_table (instance, user, item) SELECT 919191, 123, 456 
WHERE (SELECT COUNT(*) FROM x_table WHERE user=123 AND item=456) = 0

Ya da belki çalıştırıp çalıştırmayacağınızı belirlemek için herhangi bir karmaşık mantık kullanmadığınız için , bu iki sütunun birleşimi için INSERTbir UNIQUEanahtar ayarlayabilir ve sonra kullanabilirsiniz INSERT IGNORE.


Cevabını verdin mi? Devam ediyorum ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where...(5.6.34'te)
hlin117

Daha from dualönce söylemen gerektiğini düşünüyorum where.
hlin117

@ hlin117 FROM DUALHerhangi bir tabloya başvurulmadıysa MariaDB varsayılandır ( bu belgeye bakın ).
Yeti

1

(X_table.user, x_table.item) benzersiz olan bir kısıt eklerseniz, aynı kullanıcı ve öğe ile başka bir satır eklemek başarısız olur.

Örneğin:

mysql> create table x_table ( instance integer primary key auto_increment, user integer, item integer, unique (user, item));
Query OK, 0 rows affected (0.00 sec)

mysql> insert into x_table (user, item) values (1,2),(3,4);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> insert into x_table (user, item) values (1,6);
Query OK, 1 row affected (0.00 sec)

mysql> insert into x_table (user, item) values (1,2);
ERROR 1062 (23000): Duplicate entry '1-2' for key 2

Bu doğru değil. Aynı kullanıcıya sahip birden çok satır olabilir, ancak bir kullanıcı-öğe çiftine sahip birden çok satır olamaz.
Matthew Flaschen

Evet evet. Yanlış anladım. Çift üzerinde kısıtlama yapmak için düzenlendi.
NickZoic

Güzel yorum ... PHP'de mysql_query ("INSERT") kullanarak sorguyu çalıştırıyorum ve or die
Parçasını

1

Verilerinizi eklemeden önce yinelemeyi kontrol etmek iyi olsa da, yanlışlıkla yinelenen verilerin eklenmemesi için sütunlarınıza benzersiz bir kısıtlama / dizin koymanızı öneririm.


1

Sorununuzu çözmek için aşağıdaki çözümü kullanabilirsiniz:

INSERT INTO x_table(instance, user, item) 
    SELECT 919191, 123, 456
        FROM dual
        WHERE 123 NOT IN (SELECT user FROM x_table)

Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek bağlam sağlamak, yanıtlayanın uzun vadeli değerini artıracaktır.
Nic3500

0

Alex'in cevabında küçük bir değişiklik, sadece mevcut sütun değerine de başvurabilirsiniz:

Insert into x_table (instance, user, item) values (919191, 123, 456) 
  ON DUPLICATE KEY UPDATE user=user

0

Bu, PostgreSQL'in kısaltmasıdır

INSERT INTO x_table
SELECT NewRow.*
FROM (SELECT 919191 as instance, 123 as user, 456 as item) AS NewRow
LEFT JOIN x_table
ON x_table.user = NewRow.user AND x_table.item = NewRow.item
WHERE x_table.instance IS NULL

-1
Insert into x_table (instance, user, item) values (919191, 123, 456) 
    where ((select count(*) from x_table where user=123 and item=456) = 0);

Sözdizimi, DB'nize bağlı olarak değişebilir ...


2
Bu ne için? MySQL?
Umair A.
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.