2010-11-05 10 views
6

काम नहीं करता मैं एक INSERT बयान है कि इस तरह दिखता है:पर नकली चाबी अद्यतन जब वहाँ कोई अपडेट प्रारंभ

INSERT INTO officer (officer_number, 
        name, 
        bank_id)  
VALUES ('', 
     '', 
     8) 

ON DUPLICATE KEY UPDATE officer_number = '', 
         name = '', 
         bank_id = 8, 
         id = LAST_INSERT_ID(id) 

यह कर के इस तरह ठीक काम कर रहा है। यह काम करना बंद कर जब मैं निम्नलिखित ट्रिगर कहा:

CREATE TRIGGER officer_update BEFORE UPDATE ON `officer` 
FOR EACH ROW SET NEW.updated_at = NOW(), NEW.created_at = OLD.created_at 

ऐसा नहीं है कि officer रिकॉर्ड डाला जाता है नहीं कर रहा है हो रही है। ऐसा लगता है कि ट्रिगर LAST_INSERT_ID() या कुछ अपहरण कर रहा है। मैं कहता हूँ इस वजह अगले क्वेरी कि मार डाला है यह है:

INSERT INTO account (import_id, 
        branch_id, 
        account_number, 
        officer_id, 
        customer_id, 
        open_date, 
        maturity_date, 
        interest_rate, 
        balance, 
        opening_balance) 
VALUES ('123', 
     '4567', 
     '789', 
     '0', # This is the officer id which is of course invalid 
     '321', 
     '1992-04-22', 
     '2012-05-22', 
     '0.0123', 
     '0', 
     '10000') 

जब से मैं एक ही सटीक फ़ाइल के साथ सफल आयात के दर्जनों दौड़े हैं, मैं नहीं मेरा कोड बदल दिया है, और अब मेरी आयात काम नहीं कर रहे इस ट्रिगर को जोड़ने के बाद, मुझे यह समझना होगा कि ट्रिगर अपराधी है। मेरे पास एक और टेबल के साथ एक समान स्थिति थी और ट्रिगर को हटाने से समस्या ठीक हो गई।

तो मेरी प्रश्न हैं:

  1. कोई व्याख्या कर सकते हैं क्या, विशेष रूप से, खड़ी कर रहा है मेरी अधिकारी आईडी 0 पर सेट करने के लिए? इस समस्या का एक अच्छा समाधान
  2. क्या है?

मैं officer.created_at पर एक और ट्रिगर (और अन्य तालिकाओं 'created_at रों का एक बहुत) है और मैं अजीब समाधान के कुछ प्रकार से बचने के लिए मैं कहाँ created_at पर एक ट्रिगर लेकिन updated_at पर एक DEFAULT CURRENT_TIMESTAMP है पसंद करेंगे। किसी कारण से, MySQL केवल तालिका के अनुसार एक ऑटो टाइमस्टैम्प की अनुमति देता है, तो मैं created_at और updated_at दोनों के लिए CURRENT_TIMESTAMP नहीं कर सकते।

यहाँ officer के लिए SHOW CREATE TABLE है:

CREATE TABLE `officer` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `officer_number` varchar(255) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `bank_id` bigint(20) NOT NULL, 
    `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `officer_number` (`officer_number`,`name`), 
    UNIQUE KEY `officer_number_2` (`officer_number`,`bank_id`), 
    KEY `bank_id` (`bank_id`), 
    CONSTRAINT `officer_ibfk_1` FOREIGN KEY (`bank_id`) REFERENCES `bank` (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=102735 DEFAULT CHARSET=latin1 
+0

क्या आप 'SHOW CREATE तालिका अधिकारी' के परिणाम पोस्ट कर सकते हैं और क्वेरी गलत तरीके से काम करती है? आपका शीर्षक 'डिप्लिकेट कुंजी अपडेट' पर कहता है लेकिन पोस्ट में ऐसी कोई प्रश्न नहीं है। – Quassnoi

+0

वूप्स। अच्छी पकड़। मैंने सवाल अपडेट कर लिया है। –

+0

क्या आप अपना कोड पेस्ट कर सकते हैं जिसका उपयोग आप * retasve * 'LAST_INSERT_ID()' के मान पर करते हैं? ऐसा लगता है कि मेरी मशीन MySQL 5.1.53 –

उत्तर

4

आपकी INSERT ... ON DUPLICATE KEY UPDATEofficer_number पहले से मौजूद होने पर त्रुटि को रोकने का एक तरीका प्रतीत होता है। आप (ट्रिगर उस समय सक्रिय करने के लिए) होने के लिए अद्यतन की आवश्यकता है, या आप इसके बजाय INSERT IGNORE इस्तेमाल कर सकते हैं:

INSERT IGNORE INTO officer (officer_number, 
        name, 
        bank_id)  
VALUES ('', 
     '', 
     8); 

कि बस कुछ भी नहीं होता अगर officer_id पहले से ही मौजूद है (और इसलिए LAST_INSERT_ID() इस प्रकार अद्यतन के लिए की जरूरत को हटाने) पूरी तरह से।

अगर यह संभव नहीं है, तो शायद आपके INSERT ... ON DUPLICATE KEY UPDATE फेरबदल हो सकता है।मैं करने के उद्देश्य के बारे में स्पष्ट नहीं कर रहा हूँ:

id = LAST_INSERT_ID(id) 

LAST_INSERT_ID() (किसी भी तर्क के बिना), पहला स्वचालित रूप से उत्पन्न मूल्य कि सबसे हाल ही में मार डाला सम्मिलित बयान से एक AUTO_INCREMENT स्तंभ इस तरह के एक स्तंभ को प्रभावित करने के लिए स्थापित किया गया था देता है।

हालांकि, अगर आप एक तर्क की आपूर्ति, यह उस तर्क के मूल्य, और LAST_INSERT_ID() के बगल में कॉल (किसी भी तर्क के बिना) देता है, एक ही मान देता है।

SELECT LAST_INSERT_ID(100); 
+---------------------+ 
| LAST_INSERT_ID(100) | 
+---------------------+ 
|     100 | 
+---------------------+ 

SELECT LAST_INSERT_ID(); 
+------------------+ 
| LAST_INSERT_ID() | 
+------------------+ 
|    100 | 
+------------------+ 

तो, अगर हम मानते हैं कि id == 100, तो यह सच होना चाहिए::

SELECT LAST_INSERT_ID(id); 
+--------------------+ 
| LAST_INSERT_ID(id) | 
+--------------------+ 
|    100 | 
+--------------------+ 

SELECT LAST_INSERT_ID(); 
+------------------+ 
| LAST_INSERT_ID() | 
+------------------+ 
|    100 | 
+------------------+ 

कि से इसे जारी रखते हुए:

id = LAST_INSERT_ID(id) 

के रूप में ही होना चाहिए:

उदाहरण के लिए
id = id 

या, जोश डेविस द्वारा सुझाए गए अनुसार, यह बिल्कुल जरूरी नहीं होना चाहिए। क्या आपने बस id = id कोशिश की है? जब आप इसे बाहर निकालते हैं तो वास्तव में क्या होता है?

manual कहा गया है कि:

हालांकि, अगर आप LAST_INSERT_ID() और LAST_INSERT_ID (expr) के लिए संदर्भ मिश्रण, प्रभाव अपरिभाषित

और है:

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

आप LAST_INSERT_ID() और LAST_INSERT_ID(expr) दोनों का उपयोग कर रहे हैं, व्यवहार अनिर्धारित रहता है। इसके अलावा, ट्रिगर को एक कनेक्शन के रूप में माना जा सकता है (यह सीधे सर्वर पर चलाया जाता है), जबकि INSERT और CREATE स्टेटमेंट को संभवतः एक अलग कनेक्शन से बुलाया जाता है। यह देखते हुए, और संस्करणों के बीच LAST_INSERT_ID से जुड़े विभिन्न परिवर्तनों और बग्स, यह संभावना है कि आपके दृष्टिकोण के साथ समस्याएं हो सकती हैं।

जोश डेविस ने जो कहा, उस पर वापस जाना, मैं आपके INSERT कथन में id = LAST_INSERT_ID(id) के उपयोग को हल करने के इच्छुक हूं। यह जानना भी सहायक होगा कि आप officer_id को अपने INSERT INTO account कथन में कैसे प्राप्त करते हैं - जो शून्य मान प्राप्त कर रहा है।

+0

यहां मैं क्या कर रहा हूं: मैंने 'इंसर्ट इग्नोर' का उपयोग किया, लेकिन अगर मैंने इसे छोड़ दिया, तो 'LAST_INSERT_ID()' सही नहीं होगा। मेरे 'INSERT' के बाद, मैंने अभी भी जो कुछ भी रिकॉर्ड किया है, उससे मेल खाता है। यह दुनिया में सबसे संक्षिप्त समाधान नहीं हो सकता है लेकिन यह काम करता है और मैं इसके साथ गड़बड़ करने से थक गया हूं। –

0

मुझे समझ नहीं आता कि क्यों id अद्यतन करने के लिए प्रयास करें। क्या आप सिर्फ LAST_INSERT_ID() पर कॉल को हटा नहीं सकते?

INSERT INTO officer (officer_number, 
        name, 
        bank_id) 
VALUES ('', 
     '', 
     8) 

ON DUPLICATE KEY UPDATE officer_number = '', 
         name = '', 
         bank_id = 8 

इसके अलावा, आप, अपने MySQL संस्करण (और साथ ही इस्तेमाल किया इंजन) पोस्ट करना चाहिए के रूप में वहाँ अतीत में LAST_INSERT_ID() व्यवहार में कुछ बदलाव हो गया है।

+0

पर ठीक काम कर रहा है यह 'LAST_INSERT_ID()' के बिना काम नहीं करता है। मैं MySQL 5.1.49 और InnoDB का उपयोग कर रहा हूं। –

संबंधित मुद्दे