php - MySQL में 'मौजूद नहीं है' कैसे करें?




performance primary-key (7)

ऐसे कई जवाब हैं जो इसे हल करने के तरीके को कवर करते हैं यदि आपके पास एक UNIQUE सूचकांक है जिसे आप ON DUPLICATE KEY या INSERT IGNORE साथ जांच सकते हैं। यह हमेशा मामला नहीं है, और जैसा कि UNIQUE की लंबाई बाधा (1000 बाइट्स) है, हो सकता है कि आप इसे बदलने में सक्षम न हों। उदाहरण के लिए, मुझे वर्डप्रेस ( wp_postmeta ) में मेटाडेटा के साथ काम करना पड़ा।

अंत में मैंने इसे दो प्रश्नों के साथ हल किया:

UPDATE wp_postmeta SET meta_value = ? WHERE meta_key = ? AND post_id = ?;
INSERT INTO wp_postmeta (post_id, meta_key, meta_value) SELECT DISTINCT ?, ?, ? FROM wp_postmeta WHERE NOT EXISTS(SELECT * FROM wp_postmeta WHERE meta_key = ? AND post_id = ?);

प्रश्न 1 एक नियमित UPDATE क्वेरी है जिसके साथ कोई प्रभाव नहीं है जब प्रश्न में डेटासेट नहीं है। क्वेरी 2 एक INSERT जो किसी भी NOT EXISTS पर निर्भर करता है, यानी INSERT केवल तब निष्पादित होता है जब डेटासेट मौजूद नहीं होता है।

मैंने googling से शुरू किया, और यह article पाया जो म्यूटेक्स टेबल के बारे में बात करता है।

मेरे पास ~ 14 मिलियन रिकॉर्ड के साथ एक टेबल है। यदि मैं एक ही प्रारूप में अधिक डेटा जोड़ना चाहता हूं, तो यह सुनिश्चित करने का एक तरीका है कि मैं जो रिकॉर्ड जोड़ना चाहता हूं वह पहले से मौजूद प्रश्नों का उपयोग किए बिना मौजूद नहीं है (यानी, एक प्रश्न पूछने के लिए और एक डालने के लिए परिणाम सेट है खाली)?

क्या फ़ील्ड पर एक unique बाधा है कि अगर यह पहले से मौजूद है तो insert असफल हो जाएगा?

ऐसा लगता है कि केवल एक बाधा के साथ, जब मैं php के माध्यम से सम्मिलन जारी करता हूं, तो स्क्रिप्ट क्रोक हो जाती है।


निम्नलिखित आज़माएं:

IF (SELECT COUNT(*) FROM beta WHERE name = 'John' > 0)
  UPDATE alfa SET c1=(SELECT id FROM beta WHERE name = 'John')
ELSE
BEGIN
  INSERT INTO beta (name) VALUES ('John')
  INSERT INTO alfa (c1) VALUES (LAST_INSERT_ID())
END

यदि कोई अपवाद स्वीकार्य है, तो किसी भी साधारण बाधा को नौकरी करना चाहिए। उदाहरण :

  • सरोगेट नहीं होने पर प्राथमिक कुंजी
  • एक कॉलम पर अद्वितीय बाधा
  • बहु कॉलम अद्वितीय बाधा

क्षमा करें यह भ्रामक रूप से सरल लगता है। मुझे पता है कि यह आपके साथ साझा किए गए लिंक से जुड़ा हुआ लगता है। ;-(

लेकिन मैं इस जवाब को कभी भी नहीं देता, क्योंकि यह आपकी ज़रूरत को भरने लगता है। (यदि नहीं, तो यह आपकी आवश्यकताओं को अपडेट करने में ट्रिगर कर सकता है, जो "एक अच्छी बात" (टीएम) भी होगी)।

संपादित किया गया : यदि कोई सम्मिलन डेटाबेस को अद्वितीय बाधा तोड़ देगा, तो ड्राइवर द्वारा रिले किए गए डेटाबेस स्तर पर एक अपवाद फेंक दिया जाता है। यह निश्चित रूप से विफलता के साथ आपकी स्क्रिप्ट को रोक देगा। उस मामले को हल करने के लिए PHP में यह संभव होना चाहिए ...


यहां एक PHP फ़ंक्शन है जो केवल एक पंक्ति डालेगा यदि सभी निर्दिष्ट कॉलम मान तालिका में पहले से मौजूद नहीं हैं।

  • यदि कॉलम में से एक भिन्न होता है, तो पंक्ति जोड़ दी जाएगी।

  • यदि तालिका खाली है, तो पंक्ति जोड़ा जाएगा।

  • यदि कोई पंक्ति मौजूद है जहां सभी निर्दिष्ट कॉलम निर्दिष्ट मान हैं, तो पंक्ति नहीं जोड़ा जाएगा।

    function insert_unique($table, $vars)
    {
      if (count($vars)) {
        $table = mysql_real_escape_string($table);
        $vars = array_map('mysql_real_escape_string', $vars);
    
        $req = "INSERT INTO `$table` (`". join('`, `', array_keys($vars)) ."`) ";
        $req .= "SELECT '". join("', '", $vars) ."' FROM DUAL ";
        $req .= "WHERE NOT EXISTS (SELECT 1 FROM `$table` WHERE ";
    
        foreach ($vars AS $col => $val)
          $req .= "`$col`='$val' AND ";
    
        $req = substr($req, 0, -5) . ") LIMIT 1";
    
        $res = mysql_query($req) OR die();
        return mysql_insert_id();
      }
    
      return False;
    }
    

उदाहरण का उपयोग:

<?php
insert_unique('mytable', array(
  'mycolumn1' => 'myvalue1',
  'mycolumn2' => 'myvalue2',
  'mycolumn3' => 'myvalue3'
  )
);
?>

Replace आपके लिए काम कर सकता है।


INSERT IGNORE INTO table उपयोग INSERT IGNORE INTO table

http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html देखें

INSERT … ON DUPLICATE KEY UPDATE भी है INSERT … ON DUPLICATE KEY UPDATE dev.mysql.com INSERT … ON DUPLICATE KEY UPDATE वाक्यविन्यास पर, आप dev.mysql.com पर स्पष्टीकरण पा सकते हैं

Google के वेबकैच के अनुसार bogdan.org.ua से पोस्ट करें:

18 अक्टूबर 2007

शुरू करने के लिए: नवीनतम MySQL के रूप में, शीर्षक में प्रस्तुत वाक्यविन्यास संभव नहीं है। लेकिन मौजूदा कार्यक्षमता का उपयोग करके अपेक्षित होने के कई आसान तरीके हैं।

3 संभावित समाधान हैं: INSERT IGNORE, स्थान, या INSERT का उपयोग करके ... डिप्लिकेट कुंजी अपडेट पर।

कल्पना कीजिए कि हमारे पास एक टेबल है:

CREATE TABLE `transcripts` (
`ensembl_transcript_id` varchar(20) NOT NULL,
`transcript_chrom_start` int(10) unsigned NOT NULL,
`transcript_chrom_end` int(10) unsigned NOT NULL,
PRIMARY KEY (`ensembl_transcript_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

अब कल्पना करें कि हमारे पास एक स्वचालित पाइपलाइन है जो एन्सेम्बल से ट्रांसक्रिप्ट मेटा-डेटा आयात करती है, और विभिन्न कारणों से पाइपलाइन निष्पादन के किसी भी चरण में टूटा जा सकता है। इस प्रकार, हमें दो चीजों को सुनिश्चित करने की आवश्यकता है: 1) पाइपलाइन के बार-बार निष्पादन हमारे डेटाबेस को नष्ट नहीं करेंगे, और 2) दोहराए गए निष्पादन 'डुप्लिकेट प्राथमिक कुंजी' त्रुटियों के कारण मर नहीं जाएंगे।

विधि 1: प्रतिस्थापन का उपयोग करना

यह बहुत सरल है:

REPLACE INTO `transcripts`
SET `ensembl_transcript_id` = ‘ENSORGT00000000001′,
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

यदि रिकॉर्ड मौजूद है, तो इसे ओवरराइट किया जाएगा; यदि यह अभी तक अस्तित्व में नहीं है, तो यह बनाया जाएगा। हालांकि, इस विधि का उपयोग हमारे मामले के लिए कुशल नहीं है: हमें मौजूदा रिकॉर्ड को ओवरराइट करने की आवश्यकता नहीं है, बस उन्हें छोड़ना ठीक है।

विधि 2: इंसर्ट इग्नोर का उपयोग करना भी बहुत आसान है:

INSERT IGNORE INTO `transcripts`
SET `ensembl_transcript_id` = ‘ENSORGT00000000001′,
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

यहां, यदि डेटाबेस में 'ensembl_transcript_id' पहले से मौजूद है, तो इसे चुपचाप छोड़ दिया जाएगा (अनदेखा)। (अधिक सटीक होने के लिए, यहां MySQL संदर्भ मैन्युअल से उद्धरण दिया गया है: "यदि आप IGNORE कीवर्ड का उपयोग करते हैं, तो INSERT कथन निष्पादित करते समय होने वाली त्रुटियों को इसके बजाय चेतावनियों के रूप में माना जाता है। उदाहरण के लिए, IGNORE के बिना, एक पंक्ति जो मौजूदा UNIQUE अनुक्रमणिका को डुप्लिकेट करती है या तालिका में प्राथमिक कुंजी मान डुप्लिकेट-कुंजी त्रुटि का कारण बनता है और कथन निरस्त कर दिया जाता है। "।) यदि रिकॉर्ड अभी तक मौजूद नहीं है, तो यह बनाया जाएगा।

इस दूसरी विधि में कई संभावित कमजोरियां हैं, जिनमें किसी अन्य समस्या के मामले में क्वेरी के गैर-गर्भपात शामिल हैं (मैन्युअल देखें)। इस प्रकार इसका उपयोग तब किया जाना चाहिए जब पहले आईजीएनओआर कीवर्ड के बिना परीक्षण किया गया हो।

एक और विकल्प है: INSERT का उपयोग करने के लिए ... डिप्लिकेट कुंजी अपडेट वाक्यविन्यास पर, और अद्यतन भाग में बस कुछ अर्थहीन (खाली) ऑपरेशन करें, जैसे कि 0 + 0 की गणना करना (Geoffray MySQL अनुकूलन के लिए id = id असाइनमेंट करने का सुझाव देता है इस ऑपरेशन को अनदेखा करने के लिए इंजन)। इस विधि का लाभ यह है कि यह केवल डुप्लिकेट कुंजी घटनाओं को अनदेखा करता है, और फिर भी अन्य त्रुटियों पर रोक लगाता है।

अंतिम नोटिस के रूप में: यह पोस्ट Xaprb से प्रेरित था। मैं लचीला एसक्यूएल प्रश्न लिखने पर अपनी दूसरी पोस्ट से परामर्श करने की भी सलाह दूंगा।


REPLACE INTO `transcripts`
SET `ensembl_transcript_id` = 'ENSORGT00000000001',
`transcript_chrom_start` = 12345,
`transcript_chrom_end` = 12678;

यदि रिकॉर्ड मौजूद है, तो इसे ओवरराइट किया जाएगा; यदि यह अभी तक अस्तित्व में नहीं है, तो यह बनाया जाएगा।





primary-key