MySQL DELETE स्थिति से उपकुंजी के साथ


85

मैं इस तरह से एक प्रश्न करने की कोशिश कर रहा हूं:

DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (
    SELECT DISTINCT(th1.tid)
    FROM term_hierarchy AS th1
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
    WHERE th1.parent = 1015
);

जैसा कि आप शायद बता सकते हैं, मैं 1015 पर माता-पिता के संबंध को हटाना चाहता हूं यदि उसी tid के अन्य माता-पिता हैं। हालाँकि, इससे मुझे एक सिंटैक्स त्रुटि मिलती है:

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 'AS th
WHERE th.parent = 1015 AND th.tid IN (
  SELECT DISTINCT(th1.tid)
  FROM ter' at line 1

मैंने दस्तावेज़ीकरण की जाँच की है, और उपकुंजी को अपने आप चला रहा है, और यह सब बाहर की जाँच करता है। क्या कोई यह पता लगा सकता है कि यहां क्या गलत है?

अद्यतन : जैसा कि नीचे उत्तर दिया गया है, MySQL आपको उस तालिका की अनुमति नहीं देता है जिसे आप किसी उपश्रेणी में उपयोग करने के लिए हटा रहे हैं।


2
ध्यान दें : नीचे stackoverflow.com/ में अच्छा जवाब / DELETE t FROM table t ...
4471359/956397

जवाबों:


38

आप हटाने के लिए लक्ष्य तालिका निर्दिष्ट नहीं कर सकते।

एक वर्कअराउंड

create table term_hierarchy_backup (tid int(10)); <- check data type

insert into term_hierarchy_backup 
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015;

DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup);

हम दोनों सही हैं - मेरे जवाब के लिए उसकी टिप्पणी नीचे देखें। उपनाम वाक्य और तर्क दोनों ही मुद्दे थे :)
JNK

हाँ, लगता है कि
सबक्विरी के

उस अंतिम पंक्ति में "DELETE FROM term_hierarchy AS वें" के समान समस्या नहीं है? मैं एक वाक्यविन्यास त्रुटि ओपी के समान है।
मल्हल

आपको index को term_hierarchy_backup.tid में जोड़ना चाहिए।
रोमन न्यूजा

1
मैं यह सत्यापित करने में सक्षम हूं कि 2019 में मारियाडीबी 10.3.14 या MySQL सामुदायिक सर्वर 5.7.27 पर यह संभव नहीं है
अल्फाम 8

283

दूसरों के लिए जो इस प्रश्न को खोजने के लिए एक सबक्वेरी का उपयोग करते हुए हटाना चाहते हैं, मैं आपको MySQL को आउटसोर्स करने के लिए इस उदाहरण को छोड़ देता हूं (भले ही कुछ लोगों को लगता है कि यह नहीं किया जा सकता है):

DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
             FROM tableE
             WHERE arg = 1 AND foo = 'bar');

आपको एक त्रुटि देगा:

ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause

हालाँकि यह प्रश्न:

DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
             FROM (SELECT id
                   FROM tableE
                   WHERE arg = 1 AND foo = 'bar') x);

ठीक काम करेगा:

Query OK, 1 row affected (3.91 sec)

अपने मातहत को एक अतिरिक्त उपवर्ग में लपेटें (यहां x नाम दिया गया है) और MySQL खुशी से आपके द्वारा पूछे गए कार्यों को करेगा।


10
कुछ समय लगा लेकिन मुझे काम करने के लिए मिल गया। महत्वपूर्ण: 1) पहली तालिका को "ई", 2 के साथ यहां दिखाया गया होना चाहिए, अंत में "x" एक प्लेसहोल्डर नहीं है, यह उपकुंजी द्वारा निर्मित अस्थायी तालिका के लिए उपनाम है "(तालिका से आईडी का चयन करें) जहाँ arg = 1 और foo = 'bar') "।
तिलमन होउशर

3
यह काम क्यों करता है? यह मेरे लिए बहुत कुछ बदलता है, लेकिन इसके अलावा, यह काम नहीं करना चाहिए। यह काम करता है , लेकिन यह नहीं होना चाहिए।
21

1
अविश्वसनीय। यह वास्तव में काम करता है! लेकिन आप ई के साथ तालिका को उर्फ ​​करने के लिए मजबूर नहीं हैं ... आप किसी भी अन्य उपनाम का उपयोग कर सकते हैं जिसे आप चाहते हैं।
आंद्रेई सैंडुल्स्क्यू

1
@jakabadambalazs मेरा तर्क जब इसके साथ आ रहा था, तो यह था कि "सेलेक्ट आईडी" के साथ शुरू होने वाली उपश्रेणी आईडी की सूची को समाप्त कर देती है और इसलिए उस तालिका का लॉक जारी करती है जिसे आप हटाना चाहते हैं।
कोडर सस्ता

9
@jakabadambalazs: हम eDELETE में और इसके उप-चयन में एक ही तालिका ( ) का उपयोग नहीं कर सकते हैं । हम कर सकते हैं , फिर भी एक उप उप चयन अस्थायी तालिका (बनाने के लिए उपयोग x), और उपयोग कि उप चयन के लिए।
स्टीव बादाम

39

DELETEकीवर्ड के बाद उपनाम शामिल किया जाना चाहिए :

DELETE th
FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN 
(
    SELECT DISTINCT(th1.tid)
    FROM term_hierarchy AS th1
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
    WHERE th1.parent = 1015
);

3
यह एक अच्छा जवाब है। मूल पोस्ट के समान समस्याओं को हल करने के लिए उचित एलियासिंग एक लंबा रास्ता तय करेगी। (मेरी तरह।)
usumoio

10

आपको डिलीट स्टेटमेंट में फिर से उपनाम का उल्लेख करना होगा, जैसे:

DELETE th FROM term_hierarchy AS th
....

जैसा कि यहाँ MySQL डॉक्स में दिया गया है।


उर्फ के बारे में नहीं है, कृपया ओपी को फिर से
जांचें

@ajreal - मैंने किया था, और कृपया ध्यान दें कि त्रुटि उपनाम की परिभाषा से शुरू होती है, और MySQL प्रलेखन में स्पष्ट रूप से कहा गया है कि आपको उपनाम के साथ ही कथन से भी उपयोग करने की आवश्यकता है। हालांकि, डाउनवोट के लिए धन्यवाद।
जेएनके

बस delete from your_table as t1 where t1.id in(select t2.id from your_table t2);आपको यह क्या मिला?
अंजुरल

4
दस्तावेज में स्पष्ट रूप से कहा गया है; Currently, you cannot delete from a table and select from the same table in a subquery. dev.mysql.com/doc/refman/5.5/en/delete.html
ब्योर्न

1
आपको उपनाम को ठीक करने की आवश्यकता नहीं है, बस डिलीट में चयन करने के लिए लक्ष्य तालिका निर्दिष्ट न करें ... यह वास्तविक समस्या है
ajreal

7

मैंने इसे कुछ अलग तरीके से संपर्क किया और इसने मेरे लिए काम किया;

मुझे secure_linksअपनी तालिका से हटाने की ज़रूरत थी जो उस तालिका का संदर्भ देती conditionsहै जहां अब कोई भी स्थिति पंक्तियाँ नहीं बची थीं। एक हाउसकीपिंग स्क्रिप्ट मूल रूप से। इससे मुझे त्रुटि मिली - आप हटाने के लिए लक्ष्य तालिका निर्दिष्ट नहीं कर सकते।

इसलिए प्रेरणा की तलाश में मैं नीचे क्वेरी के साथ आया और यह ठीक काम करता है। ऐसा इसलिए है क्योंकि यह एक अस्थायी तालिका बनाता sl1है जिसका उपयोग DELETE के लिए संदर्भ के रूप में किया जाता है।

DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN 
            (
            SELECT
                `sl1`.`link_id` 
            FROM 
                (
                SELECT 

                    `sl2`.`link_id` 

                FROM 
                    `secure_links` AS `sl2` 
                    LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job` 

                WHERE 

                    `sl2`.`action` = 'something' AND 
                    `conditions`.`ref` IS NULL 
                ) AS `sl1`
            )

मेरे लिये कार्य करता है।


5

डिलीट में "इन" क्लॉज़ नहीं है ... जहाँ, बेहद अक्षम, अगर वहाँ बड़ी संख्या में सबकुछ मान कर लौटे हैं? यह निश्चित नहीं है कि आप हमें हटाने के लिए ID (सबक्वेरी) के बजाय ID पर सबक्वेरी से मूल तालिका के विरुद्ध वापस क्यों नहीं जुड़ेंगे?

DELETE T FROM Target AS T
RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID)

और शायद यह "MySQL की अनुमति नहीं देता है" में इसका उत्तर दिया गया है, हालांकि, यह मेरे लिए ठीक काम कर रहा है कि मैं पूरी तरह से स्पष्ट कर दूं कि क्या हटाना है (DELETE T FROM Target AS T)। MySQL में Join के साथ Delete DELETE / JOIN समस्या को स्पष्ट करता है।


2

यदि आप 2 प्रश्नों के साथ ऐसा करना चाहते हैं, तो आप हमेशा ऐसा ही कुछ कर सकते हैं:

1) के साथ तालिका से आईडी हड़पने:

SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...

फिर XXX के नीचे माउस / कीबोर्ड या प्रोग्रामिंग भाषा के साथ परिणाम की प्रतिलिपि बनाएँ:

2) DELETE FROM your_table WHERE id IN ( XXX )

शायद आप इसे एक क्वेरी में कर सकते हैं, लेकिन यह वही है जो मुझे पसंद है।


0

@ कोडरोड, @ बेनीहिल: यह उम्मीद के मुताबिक काम करता है।

हालाँकि, मैं तालिका में लाखों पंक्तियों के लिए समय की जटिलता को आश्चर्यचकित करता हूं? जाहिर है, यह 5msसही ढंग से अनुक्रमित तालिका पर 5k रिकॉर्ड रखने के लिए निष्पादित करने के बारे में था।

मेरी क्वेरी:

SET status = '1'
WHERE id IN (
    SELECT id
    FROM (
      SELECT c2.id FROM clusters as c2
      WHERE c2.assign_to_user_id IS NOT NULL
        AND c2.id NOT IN (
         SELECT c1.id FROM clusters AS c1
           LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id
           LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id
         WHERE ft.slug = 'closed'
         )
      ) x)```

Or is there something we can improve on my query above?

0

आप डिलीट स्टेटमेंट पर इस तरह से अन्य का उपयोग कर सकते हैं

DELETE  th.*
FROM term_hierarchy th
INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th.parent = 1015;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.