MySQL: तालिका में मौजूद नहीं होने पर रिकॉर्ड डालें


384

मैं निम्नलिखित क्वेरी को निष्पादित करने का प्रयास कर रहा हूं:

INSERT INTO table_listnames (name, address, tele)
VALUES ('Rupert', 'Somewhere', '022')
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name='value'
);

लेकिन यह एक त्रुटि देता है। मूल रूप से मैं एक रिकॉर्ड सम्मिलित नहीं करना चाहता हूं यदि रिकॉर्ड का 'नाम' फ़ील्ड पहले से ही किसी अन्य रिकॉर्ड में मौजूद है - अगर नया नाम अद्वितीय है तो कैसे जांचें?



12
इस या उत्तर के सभी वर्तमान उत्तर यह मानते हैं कि आप एक अद्वितीय सूचकांक जोड़ सकते हैं। कभी-कभी निर्णय व्यापार तर्क पर आधारित होता है जिसे पूरी मेज पर नहीं लगाया जा सकता है। उदाहरण के लिए, आप एक स्तंभ में एक निश्चित मान के साथ कई पंक्तियों को अनुमति देते हैं, लेकिन स्तंभ में एक और मूल्य केवल एक पंक्ति में प्रदर्शित होने की अनुमति होगी। हम इसे कैसे पूरा करेंगे?
ऑस्कर

जवाबों:


502

मैं वास्तव में सुझाव नहीं दे रहा हूं कि आप ऐसा करते हैं, जैसा कि UNIQUEपिस्कवर द्वारा सुझाए गए सूचकांक और अन्य इसे करने के लिए एक बेहतर तरीका है, लेकिन आप वास्तव में वही कर सकते हैं जो आप प्रयास कर रहे थे:

CREATE TABLE `table_listnames` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `address` varchar(255) NOT NULL,
  `tele` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB;

एक रिकॉर्ड डालें:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

SELECT * FROM `table_listnames`;

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
+----+--------+-----------+------+

उसी रिकॉर्ड को फिर से सम्मिलित करने का प्रयास करें:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Rupert', 'Somewhere', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;

Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
+----+--------+-----------+------+

एक अलग रिकॉर्ड डालें:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'John'
) LIMIT 1;

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

SELECT * FROM `table_listnames`;

+----+--------+-----------+------+
| id | name   | address   | tele |
+----+--------+-----------+------+
|  1 | Rupert | Somewhere | 022  |
|  2 | John   | Doe       | 022  |
+----+--------+-----------+------+

और इसी तरह...


अपडेट करें:

#1060 - Duplicate column nameयदि दो मान बराबर हो सकते हैं, तो त्रुटि को रोकने के लिए , आपको आंतरिक चयन के कॉलम का नाम देना होगा:

INSERT INTO table_listnames (name, address, tele)
SELECT * FROM (SELECT 'Unknown' AS name, 'Unknown' AS address, '022' AS tele) AS tmp
WHERE NOT EXISTS (
    SELECT name FROM table_listnames WHERE name = 'Rupert'
) LIMIT 1;

Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

SELECT * FROM `table_listnames`;

+----+---------+-----------+------+
| id | name    | address   | tele |
+----+---------+-----------+------+
|  1 | Rupert  | Somewhere | 022  |
|  2 | John    | Doe       | 022  |
|  3 | Unknown | Unknown   | 022  |
+----+---------+-----------+------+

18
धन्यवाद जिसने मदद की। मेरी वास्तविक समस्या कहीं अधिक जटिल है और कॉलम केवल अद्वितीय नहीं हो सकता है और मैं प्राथमिक कुंजी पर निर्भर नहीं कर सकता। लेकिन यह वही है जिसकी मुझे तलाश थी।
रूपर्ट

2
@Piskovar: सहमत। @Rupert: nameयदि संभव हो तो आपको आंतरिक चयन कथन ( , इस मामले में) में निर्दिष्ट कॉलम को अनुक्रमित करना चाहिए । यह भी ध्यान दें कि आप कर सकते हैं - के SELECT 'John', 'Doe', '022' FROM table_listnamesबजाय SELECT * FROM (SELECT 'John', 'Doe', '022') AS tmp- लेकिन वह केवल तभी काम करेगा जब table_listnamesपहले से ही एक या अधिक पंक्तियाँ हों। मुझे संदेह है कि गति किसी भी अलग है, लेकिन यह शायद एक चिंता का विषय नहीं है।
माइक

3
@VijayRamamurthy: यह काम करता है क्योंकि आप एक चयन कथन का परिणाम सम्मिलित करते हैं। क्वेरी को ध्यान से पढ़ें -> WHEREकथन SELECTक्वेरी का है। चयन करें क्वेरी या तो एक एकल डेटा-पंक्ति (डेटा डाला जाता है) या कोई डेटा बिल्कुल नहीं डाला जाता है (कुछ भी नहीं डाला जाता है)
फिलिप्पी

13
यदि आप एक ही मूल्य को अलग-अलग क्षेत्रों में दो बार सम्मिलित करना चाहते हैं (जैसे SELECT 'Humbert', 'Humbert', '1'कि आंतरिक चयन में)। मैं एक प्राप्तERROR 1060 (42S21): Duplicate column name
cburgmer

28
@ Cburgmer मैं एक ही समस्या है #1060 - Duplicate column name। क्या आपने हल खोज लिया? संपादित करें: यह मिला। प्रत्येक मान के पीछे एक एएस जोड़ें:SELECT * FROM (SELECT 'Rupert' as name, 'Rupert' as friend, '022' as number) AS tmp
काई नैक

292

INSERT WHEREसिंटैक्स में अनुमति नहीं देता है

आप क्या कर सकते हैं: UNIQUE INDEXउस फ़ील्ड पर बनाएं जो अद्वितीय होना चाहिए ( name), फिर या तो उपयोग करें:

  • सामान्य INSERT(और नाम पहले से मौजूद होने पर त्रुटि को संभालें)
  • INSERT IGNORE(जो पहले से मौजूद है तो गलती से चेतावनी के बजाय (त्रुटि के बजाय) विफल हो जाएगी )
  • INSERT ... ON DUPLICATE KEY UPDATE(जो UPDATEपहले से मौजूद नाम के अंत में निष्पादित होगा , प्रलेखन देखें )

1
यदि आपको चेतावनी संदेश प्राप्त करने की आवश्यकता है तो आप बाद में कर सकते हैंmysql> show warnings\G
fiorentinoing

2
ime, चेतावनी संदेश, के मामले में INSERT IGNORE, regex से मेल खाता है^Duplicate entry '.+' for key '.+'$
user2426679

1
यदि आप इन्सर्ट इग्नोर का उपयोग करते हैं, तो क्या यह अन्य त्रुटियों की अनदेखी करेगा जो डुप्लिकेट के कारण नहीं हैं?
gepex

1
@gepex हाँ, यह होगा। INSERT IGNOREIMO का उपयोग करने के साथ यह एक बड़ी समस्या है ।
shmosel

1
नोट: यह उत्तर सबसे अच्छा विकल्प नहीं हो सकता है यदि अद्वितीय कुंजी बाधा में से एक स्तंभ अशक्त है! बाधा काम करती है, लेकिन आप अन्य परिणामों की उम्मीद कर सकते हैं :) सम्मिलित करना ("जॉन डो", NULL), ("जॉन डो", NULL) दो पंक्तियों में परिणाम देता है, हालांकि दोनों फ़ील्ड एक साथ एक अद्वितीय कुंजी बाधा में हैं। इसके अलावा stackoverflow.com/questions/4081783/unique-key-with-nulls
Piemol

57

काम किया:

INSERT INTO users (full_name, login, password) 
  SELECT 'Mahbub Tito','tito',SHA1('12345') FROM DUAL
WHERE NOT EXISTS 
  (SELECT login FROM users WHERE login='tito');

यह केवल Oracle डेटाबेस के लिए काम करता है? en.wikipedia.org/wiki/DUAL_table यह प्रश्न विशेष रूप से MySQL के बारे में है!
अत्यधिक अनियमित

1
मैं Oracle डेटाबेस में परीक्षण नहीं करता। यह MySQL और परीक्षण में ठीक काम कर रहा है।
महबूब टीटो

9
जब से मैंने सीखा कि "ड्यूल" MySQL में उपलब्ध है, लेकिन मारियाडीबी में नहीं, MySQL की ओपन सोर्स शाखा
अत्यधिक अनियमित

3
@ HighlyIr अनियमित की विकिपीडिया लिंक से "कई अन्य डेटाबेस (जिसमें Microsoft SQL Server, MySQL, PostgreSQL, SQLite, और Teradata शामिल हैं) एक को पूर्ण तालिका से पूरी तरह से हटाने में सक्षम करते हैं यदि कोई तालिका आवश्यक नहीं है। यह किसी भी डमी तालिका की आवश्यकता को टालता है।" ऐसा लगता है कि MySql (5.7, यदि वह मायने रखता है) से FROM DUAL के बिना काम करता है।
स्टेनियस

1
परीक्षण किया और मारियाडीबी में ठीक काम कर रहा है! साभार @MahbubTito
जेफ

27

MySQL बहुत प्यारा समाधान प्रदान करता है:

REPLACE INTO `table` VALUES (5, 'John', 'Doe', SHA1('password'));

उपयोग करने में बहुत आसान है क्योंकि आपने एक अद्वितीय प्राथमिक कुंजी (मूल्य 5 के साथ) घोषित की है।


इसे रोकने के लिए आपको एक अद्वितीय सूचकांक बनाने की आवश्यकता है, यहाँ अधिक जानकारी: लिंक
अज़मेर

बहूत खतरनाक। जब तक आप यह नहीं जानते कि आप क्या कर रहे हैं, तब तक प्रयास न करें। वास्तव में, बिल्कुल भी प्रयास न करें। अन्य उत्तरों की जाँच करें।
झौरलाद एस्ट्रेला

3
ध्यान दें, यह किसी भी मेल खाने वाली पंक्तियों को हटाता है और फिर उन्हें फिर से सम्मिलित करता है, इसी व्यवहार का एक सुरक्षित संस्करण DUPLICTE KEY UPDATE का उपयोग करना है, जो कि पंक्तियों को हटाने और उन्हें फिर से सम्मिलित करने के बजाय गणित को अद्यतन करता है: dev.ysql.com/doc/ Refman / 5.7 / en /
replace.html

22
INSERT IGNORE INTO `mytable`
SET `field0` = '2',
`field1` = 12345,
`field2` = 12678;

यहाँ mysql क्वेरी, जो रिकॉर्ड मौजूद है यदि मौजूद नहीं है और मौजूदा समान रिकॉर्ड को अनदेखा करेगी।

----Untested----

4
यह मेरे लिए काम नहीं करता है, INSERT IGNORE INTO emAssignedTagsForEvent SET eventId = '2', defaultTagId = '1';
पितु

8
इन्सर्ट और अपडेट सिंटैक्स का मिश्रण लगता है। क्या आपका मतलब है INSERT IGNORE INTO `mytable` (`field0`, `field1`, `field2`) values ('2', 12345, 12678);?
होबो

@Hobo MySQL मैनुअल से dev.mysql.com/doc/refman/5.7/en/insert.html INSERT सिंटैक्स: यह INSERT [...] IGNORE INTO mytable VALUES ...या हो सकता हैINSERT [...] IGNORE INTO mytable SET col_name={expr | DEFAULT},...
Shirkam

"यदि आप IGNORE संशोधक का उपयोग करते हैं, तो INSERT स्टेटमेंट निष्पादित करते समय होने वाली त्रुटियों को नजरअंदाज कर दिया जाता है।" इसलिए मूल रूप से आपने कुछ भी हल नहीं किया।
मार्सेलो एगमोवेल

18

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

INSERT INTO ... ON DUPLICATE KEY UPDATE ...

इस तरह से आप किसी भी नए कच्चे को सम्मिलित कर सकते हैं और यदि आपके पास डुप्लिकेट डेटा है, तो विशिष्ट कॉलम (सर्वश्रेष्ठ कॉलम टाइमस्टैम्प है) को बदलें।
उदाहरण के लिए :

CREATE TABLE IF NOT EXISTS Devices (
  id         INT(6)       NOT NULL AUTO_INCREMENT,
  unique_id  VARCHAR(100) NOT NULL PRIMARY KEY,
  created_at VARCHAR(100) NOT NULL,
  UNIQUE KEY unique_id (unique_id),
  UNIQUE KEY id (id)
)
  CHARACTER SET utf8
  COLLATE utf8_unicode_ci;

INSERT INTO Devices(unique_id, time) 
VALUES('$device_id', '$current_time') 
ON DUPLICATE KEY UPDATE time = '$current_time';

13

यदि आप वास्तव में मेज पर एक अद्वितीय सूचकांक प्राप्त नहीं कर सकते हैं, तो आप कोशिश कर सकते हैं ...

INSERT INTO table_listnames (name, address, tele)
    SELECT 'Rupert', 'Somewhere', '022'
        FROM some_other_table
        WHERE NOT EXISTS (SELECT name
                              FROM table_listnames
                              WHERE name='Rupert')
        LIMIT 1;

12

इसी तरह की समस्या को दूर करने के लिए, मैंने एक अद्वितीय कॉलम रखने के लिए तालिका को संशोधित किया है। आपके उदाहरण का उपयोग करते हुए, सृजन पर मेरे पास कुछ इस तरह होगा:

name VARCHAR(20),
UNIQUE (name)

और फिर इसमें डालते समय निम्नलिखित प्रश्न का उपयोग करें:

INSERT IGNORE INTO train
set table_listnames='Rupert'

मैं इस समाधान को पसंद करता हूं।
इलियास करीम

9

यह क्वेरी अच्छी तरह से काम करती है:

INSERT INTO `user` ( `username` , `password` )
    SELECT * FROM (SELECT 'ersks', md5( 'Nepal' )) AS tmp
    WHERE NOT EXISTS (SELECT `username` FROM `user` WHERE `username` = 'ersks' 
    AND `password` = md5( 'Nepal' )) LIMIT 1

और आप निम्नलिखित क्वेरी का उपयोग करके तालिका बना सकते हैं:

CREATE TABLE IF NOT EXISTS `user` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(30) NOT NULL,
    `password` varchar(32) NOT NULL,
    `status` tinyint(1) DEFAULT '0',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

नोट: पहली क्वेरी का उपयोग करने का प्रयास करने से पहले दूसरी क्वेरी का उपयोग करके तालिका बनाएं।


md5 पासवर्ड हैश .... yikes!
चाड ग्रांट

4

ब्रायन हूपर: आप लगभग इस बिंदु से टकराते हैं, लेकिन आपके सिनेटैक्स में एक त्रुटि है। आपका इंसर्ट कभी नहीं होगा। मैंने अपने डेटाबेस पर परीक्षण किया और यहाँ सही उत्तर दिया गया है:

INSERT INTO podatki (datum,ura,meritev1,meritev1_sunki,impulzi1,meritev2,meritev2_sunki,impulzi2)
            SELECT '$datum', '$ura', '$meritve1','$sunki1','$impulzi1','$meritve2','$sunki2','$impulzi2'
                FROM dual
                WHERE NOT EXISTS (SELECT datum,ura
                                      FROM podatki
                                      WHERE datum='$datum' and ura='$ura'

मैं आपको y तालिका का अपना उदाहरण दे रहा हूं। इन्सर्ट लगभग वैसा ही है जैसा बियान हूपर ने लिखा था, सिवाय इसके कि मैं दूसरे टेबल से चुनिंदा डीयूएलटी ऑन्ट डालूं। सिंध का संबंध है, इवान


2
वह "दोहरी" क्या है? एक खोजशब्द में बनाया? ब्रायन ने जो कहा उससे मुझे अंतर नहीं दिखता ... EDIT: आगे की जांच मिली-जुली और विरोधाभासी (?) नतीजे मिली। जबकि SQL DUAL तालिका पृष्ठ कहता है कि MySQL DUAL तालिकाओं का समर्थन नहीं करता है, MySQL मैनुअल का कहना है कि यह करता है। मेरा स्वयं का परीक्षण दिखाता है कि यह नहीं है, क्योंकि यह unknown table status: TABLE_TYPEसंदेश देता है , हालांकि क्वेरी के परिणामस्वरूप परिणाम मिला। शायद इसलिए कि MySQL को FROM DUALक्लॉज़ की आवश्यकता नहीं है ?
२.५५


3

आप परिणाम अपडेट नहीं कर रहे हैं। आप नाम कॉलम को प्राथमिक कॉलम में परिभाषित कर सकते हैं या सेट कर सकते हैं यह अद्वितीय है।


3

मुझे एक समस्या थी, और जिस विधि से माइक ने आंशिक रूप से काम करने की सलाह दी थी, उसके लिए मेरे पास एक त्रुटि थी, जिसका नाम था कॉलम नाम = '0', और इस क्वेरी के सिंटैक्स को इस रूप में बदल दिया।

     $tQ = "INSERT  INTO names (name_id, surname_id, sum, sum2, sum3,sum4,sum5) 
                SELECT '$name', '$surname', '$sum', '$sum2', '$sum3','$sum4','$sum5' 
FROM DUAL
                WHERE NOT EXISTS (
                SELECT sum FROM names WHERE name_id = '$name' 
AND surname_id = '$surname') LIMIT 1;";

समस्या स्तंभ नामों के साथ थी। sum3, sum4 के बराबर था और mysql ने dublicate column names फेंक दिए, और मैंने इस सिंटैक्स में कोड लिखा और यह पूरी तरह से काम करता है,


1
DUAL का मालिक SYS (SYS डेटा डिक्शनरी का मालिक है, इसलिए DUAL डेटा डिक्शनरी का हिस्सा है।) लेकिन DUAL को किसी भी उपयोगकर्ता द्वारा एक्सेस किया जा सकता है। तालिका में एक एकल VARCHAR2 (1) स्तंभ है जिसे DUMMY कहा जाता है जिसमें 'X' का मान होता है। MySQL DUAL को उन प्रश्नों में एक तालिका के रूप में निर्दिष्ट करने की अनुमति देता है, जिन्हें किसी तालिका से डेटा की आवश्यकता नहीं होती है। DUAL तालिका Oracle और अन्य डेटाबेस स्थापनाओं में डिफ़ॉल्ट रूप से मौजूद एक विशेष एक-पंक्ति, एक-स्तंभ तालिका है। ओरेकल में, तालिका में एक एकल VARCHAR2 (1) कॉलम है जिसे DUMMY कहा जाता है जिसमें 'X' का मान होता है। यह SYSDATE या USER जैसे छद्म स्तंभ का चयन करने में उपयोग के लिए उपयुक्त है।
अदनान हैदर

3

मेरे पास एक समान समस्या थी और मुझे मौजूदा नहीं होने पर कई सम्मिलित करने की आवश्यकता थी। इसलिए ऊपर दिए गए उदाहरणों से मैं इस संयोजन में आया था ... यह सिर्फ यहाँ है अगर किसी को इसकी आवश्यकता होगी।

सूचना: मुझे हर जगह नाम को परिभाषित करना था क्योंकि MSSQL को इसकी आवश्यकता थी ... MySQL * के साथ भी काम करता है।

INSERT INTO names (name)
SELECT name
FROM
(
  SELECT name
  FROM
  (
     SELECT 'Test 4' as name
  ) AS tmp_single
  WHERE NOT EXISTS
  (
     SELECT name FROM names WHERE name = 'Test 4'
  )
  UNION ALL
  SELECT name
  FROM
  (
     SELECT 'Test 5' as name
  ) AS tmp_single
  WHERE NOT EXISTS
  (
     SELECT name FROM names WHERE name = 'Test 5'
  )
) tmp_all;

MySQL: CREATE TABLE names( OIDint (11) NOT NULL AUTO_INCREMENT, namevarchar (32) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY OID) ( ), UNIQUE KEY name_UNIQUE( name): इंजिन = InnoDB AUTO_INCREMENT = 1;

या

MSSQL: क्रिएटिव टेबल [नाम] ([OID] INT IDENTITY (1, 1) NOT NULL, [नाम] NVARCHAR (32) NOT NULL, PRIMARY KEY CLUSTERED ([OID] ASC); [संपादित करें] [[नाम] ([नाम] ASC)]


2

इस क्वेरी का उपयोग PHP कोड में किया जा सकता है।

मेरे पास इस तालिका में एक आईडी कॉलम है, इसलिए मुझे इस आईडी कॉलम को छोड़कर सभी कॉलमों के लिए दोहराव की जांच करनी होगी:

#need to change values
SET @goodsType = 1, @sybType=5, @deviceId = asdf12345SDFasdf2345;    


INSERT INTO `devices` (`goodsTypeId`, `goodsId`, `deviceId`) #need to change tablename and columnsnames
SELECT * FROM (SELECT @goodsType, @sybType, @deviceId) AS tmp
WHERE NOT EXISTS (
    SELECT 'goodsTypeId' FROM `devices` #need to change tablename and columns names
    WHERE `goodsTypeId` = @goodsType
        AND `goodsId` = @sybType
        AND `deviceId` = @deviceId
) LIMIT 1;

और अब नए आइटम को केवल SETस्ट्रिंग में कॉन्फ़िगर किए गए मानों के साथ मौजूद नहीं होने की स्थिति में जोड़ा जाएगा

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