MySQL सशर्त सम्मिलित करें


99

मुझे सशर्त INSERT बनाने में मुश्किल समय आ रहा है

मेरे पास स्तंभों (उदाहरण, उपयोगकर्ता, आइटम) के साथ x_table है जहां उदाहरण ID अद्वितीय है। मैं केवल एक नई पंक्ति सम्मिलित करना चाहता हूं यदि उपयोगकर्ता के पास पहले से ही दी गई वस्तु नहीं है।

उदाहरण के लिए उदाहरण डालने की कोशिश = 919191 उपयोगकर्ता = 123 आइटम = 456

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

सही दिशा में किसी भी मदद या मार्गदर्शन की बहुत सराहना की जाएगी।

जवाबों:


116

यदि आपका DBMS किसी इंसर्ट को अंजाम देने के समय आप किस टेबल से सेलेक्ट करते हैं, तो सीमाएं नहीं लगाते हैं:

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)

इसमें, dualकेवल एक पंक्ति के साथ एक तालिका है (मूल रूप से ओरेकल में पाया जाता है, अब mysql में भी)। तर्क यह है कि SELECT स्टेटमेंट आवश्यक मानों के साथ डेटा की एक एकल पंक्ति उत्पन्न करता है, लेकिन केवल तब जब मान पहले से नहीं मिलते हैं।

वैकल्पिक रूप से, MERGE स्टेटमेंट को देखें।


1
क्या dualइस मामले में हाथ से पहले निर्मित होने की आवश्यकता है या क्या यह अकेले क्वेरी के उपयोग के लिए क्वेरी द्वारा बनाई गई कुछ विशेष "अस्थायी" तालिका है?
itsmequinn

8
यदि आपके पास dualपहले से नहीं है , तो आपको इसे बनाने की आवश्यकता है। 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;
जोनाथन लेफ़लर

धन्यवाद कि यह जानने के लिए बहुत बढ़िया है
इसके बारे में

11
ध्यान दें, MySQL में, आपको वास्तव में मौजूद होने के लिए 'दोहरी' नामक तालिका रखने की आवश्यकता नहीं है: यह एक विशेष तालिका-नाम है जिसका उपयोग इसमें से कुछ भी चुनने के लिए किया जा सकता है।
क्रिस्टोफर शुल्त्स

3
MySQL "दोहरे" की अवधारणा का "सम्मान" करता है लेकिन यह वास्तव में मौजूद नहीं है। उदाहरण के लिए, यदि आप SELECT COUNT(*) FROM dualहमेशा प्राप्त करते हैं 1, और यदि SELECT 'foo' FROM dualआप हमेशा प्राप्त करते हैं foo। लेकिन आप ऐसा नहीं कर सकते SELECT * FROM dualऔर आप ऐसा DESCRIBE dualकुछ भी नहीं कर सकते । मैंने जाँच नहीं की है, लेकिन मुझे नहीं लगता कि आप dualया तो अनुमति रद्द कर सकते हैं। तो यह इंगित करने के लायक है कि यह आपकी अपेक्षा के अनुसार काम करता है ... सिवाय इसके कि कब नहीं?)
क्रिस्टोफर शुल्त्स

52

INSERT IGNOREजब आप किसी विशिष्ट अनुक्रमणिका (उपयोगकर्ता, आइटम) पर किसी पंक्ति को अद्यतन करने या सम्मिलित करने के बजाय चुपचाप उस प्रविष्टि का उपयोग कर सकते हैं, जिसे आप अनदेखा करते हैं।

क्वेरी इस तरह दिखाई देगी:

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

आप के साथ अद्वितीय सूचकांक जोड़ सकते हैं CREATE UNIQUE INDEX user_item ON x_table (user, item)


2
MySQL के दस्तावेज INSERT IGNORE REPLACE के प्रतिरूप है ... INSERT IGNORE: पुरानी पंक्तियों को रखें। उत्तर: नई पंक्तियों को रखें। दोनों अद्वितीय कुंजी पर काम करते हैं।
पॉल केंजोरा

अब तक का सबसे अच्छा जवाब
jmojico

30

क्या आपने कभी ऐसा कुछ करने की कोशिश की है?

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;

अरे हाँ ! सिर्फ एक सेलेक्ट स्टेटमेंट के साथ स्मार्ट और अच्छा समाधान
java acm

अच्छा लगा। यह पहले प्रयास पर पोस्टग्रैक्स्ल के लिए काम करता है, जहां स्वीकृत जवाब मेरे लिए नहीं लगता था।
मयिपाइल

10

एक के साथ UNIQUE(user, item), करो:

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

user=123बिट एक "नहीं-op" की वाक्य रचना मिलान करने के लिए है ON DUPLICATEवास्तव में कुछ भी कर रही है जब वहाँ डुप्लिकेट हैं बिना खंड।


1
मैं एक अनोखा (उपयोगकर्ता, आइटम) सेटअप नहीं कर सकता क्योंकि ऐसे उदाहरण हो सकते हैं जब एक ही उपयोगकर्ता और आइटम के साथ कई इंस्टेंसेस ... बस तब नहीं जब मैं यह सम्मिलित कर रहा हूं।
अज्ञात

3

यदि आप एक अद्वितीय बाधा निर्धारित नहीं करना चाहते हैं, तो यह एक आकर्षण की तरह काम करता है:

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

आशा करता हूँ की ये काम करेगा !


2

तुम जो चाहते हो INSERT INTO table (...) SELECT ... WHERE ...। से MySQL 5.6 मैनुअल

आपके मामले में यह है:

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

या हो सकता है कि जब से आप यह निर्धारित करने के लिए किसी भी जटिल तर्क का उपयोग नहीं कर रहे हैं कि क्या आप को चलाने के लिए INSERTया नहीं तो आप UNIQUEइन दो स्तंभों के संयोजन पर एक कुंजी सेट कर सकते हैं और फिर उपयोग कर सकते हैं INSERT IGNORE


क्या आपने अपना जवाब दिया? मैं मिलता रहा 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 रन)
hlin117

मुझे लगता है कि आपको from dualपहले कहना चाहिए where
hlin117

@ hlin117 मारियाडीबी में FROM DUALडिफ़ॉल्ट है यदि कोई तालिकाओं को संदर्भित नहीं किया गया था ( इस दस्तावेज को देखें )।
यति

1

यदि आप एक बाधा जोड़ते हैं कि (x_table.user, x_table.item) अद्वितीय है, तो उसी उपयोगकर्ता और आइटम के साथ एक और पंक्ति सम्मिलित करना विफल हो जाएगा।

उदाहरण के लिए:

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

यह सही नहीं है। एक ही उपयोगकर्ता के साथ कई पंक्तियाँ हो सकती हैं, लेकिन उपयोगकर्ता-आइटम जोड़ी के साथ एकाधिक पंक्तियाँ नहीं।
मैथ्यू फ्लैशेन

हाँ हाँ। मैंने इसे गलत बताया। जोड़ी पर कसना बनाने का संपादन किया।
निकोज़िक

अच्छी टिप्पणी ... मैं mysql_query ("INSERT") का उपयोग करके PHP में क्वेरी को चलाता हूं या छोड़ देता हूं या मर जाता हूं इसलिए यह मुझे त्रुटि के बारे में चेतावनी देता है इसलिए मुझे कोई चेक नहीं करना है
Angel.King.47x

1

हालाँकि अपना डेटा डालने से पहले डुप्लिकेट के लिए जाँच करना अच्छा है, मेरा सुझाव है कि आप अपने कॉलम में एक अद्वितीय बाधा / सूचकांक डालें ताकि कोई भी डुप्लिकेट डेटा गलती से नहीं डाला जा सके।


1

आप अपनी समस्या को हल करने के लिए निम्नलिखित समाधान का उपयोग कर सकते हैं:

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

हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन समस्या को हल करने के तरीके के बारे में अतिरिक्त संदर्भ प्रदान करता है और यह समस्या को हल करता है और उत्तर के दीर्घकालिक मूल्य में सुधार करेगा।
निक 3500

0

एलेक्स की प्रतिक्रिया के लिए थोड़ा संशोधन, आप भी मौजूदा स्तंभ मान का संदर्भ दे सकते हैं:

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

0

तो यह एक PostgreSQL के लिए खड़ा है

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);

सिंटैक्स आपके DB के आधार पर भिन्न हो सकता है ...


2
यह किस लिए है? माई एसक्यूएल?
उमैर ए।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.