php सवर कैसे डुप्लिकेट से बचने के लिए कोई मान पहले से मौजूद है या नहीं?




माय गूगल अकाउंट (14)

जवाब इस बात पर निर्भर करता है कि क्या आप जानना चाहते हैं कि डुप्लिकेट फ़ील्ड के साथ रिकॉर्ड दर्ज करने के लिए प्रयास कब किया जाता है। यदि आप परवाह नहीं करते तो "INSERT ... पर डुप्लिकेट कुंजी" वाक्यविन्यास का उपयोग करें क्योंकि इससे आपके प्रयास को चुपचाप एक डुप्लिकेट बनाने के बिना सफल हो जाएगा

यदि दूसरी ओर आप जानना चाहते हैं कि इस तरह की घटना तब होती है और इसे रोकती है, तो आपको एक अनन्य कुंजी बाधा का उपयोग करना चाहिए, जो कि प्रयास किए गए सम्मिलित / अद्यतन को सार्थक त्रुटि से विफल करने का कारण होगा।

मेरे पास यूआरएल की मेज है और मुझे कोई डुप्लिकेट यूआरएल नहीं चाहिए। मुझे यह देखने के लिए कैसे पता चलेगा कि क्या कोई दिए गए यूआरएल पहले ही PHP / MySQL का उपयोग करते हुए तालिका में है?


आप यह क्वेरी कर सकते हैं:

SELECT url FROM urls WHERE url = 'http://asdf.com' LIMIT 1

फिर जांचें कि क्या mysql_num_rows () == 1 यह देखने के लिए कि क्या यह मौजूद है।


आप एक स्वयं-मिलन का उपयोग कर ढूँढ सकते हैं (और निकालें)। आपकी तालिका में कुछ यूआरएल और कुछ पीके भी हैं (हम जानते हैं कि पीके यूआरएल नहीं है क्योंकि अन्यथा आपको डुप्लिकेट की अनुमति नहीं दी जाएगी)

SELECT
    *
FROM
    yourTable a
JOIN
    yourTable b -- Join the same table
        ON b.[URL] = a.[URL] -- where the URL's match
        AND b.[PK] <> b.[PK] -- but the PK's are different

यह उन सभी पंक्तियों को वापस करेगा जो यूआरएल को डुप्लिकेट कर चुके हैं।

कहें, हालांकि, आप केवल डुप्लिकेट का चयन करना चाहते हैं और मूल को बाहर करना चाहते हैं .... ठीक है आपको तय करना होगा कि मूल क्या है। इस उत्तर के उद्देश्य के लिए मान लें कि निम्न पीके "मूल"

आपको केवल सब कुछ करने की ज़रूरत है ऊपर की कड़ी में निम्नलिखित खंड जोड़ें:

WHERE
    a.[PK] NOT IN (
        SELECT 
            TOP 1 c.[PK] -- Only grabbing the original!
        FROM
            yourTable c
        WHERE
            c.[URL] = a.[URL] -- has the same URL
        ORDER BY
            c.[PK] ASC) -- sort it by whatever your criterion is for "original"

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

ध्यान दें कि यह दृष्टिकोण अयोग्य हो सकता है, क्योंकि भाग में mySQL हमेशा अच्छी तरह से संभाल नहीं करता है, लेकिन मैं ओपी से समझता हूं कि यह टेबल पर "साफ" है, हमेशा एक चेक नहीं।

यदि आप INSERT समय पर जांचना चाहते हैं कि कोई मान पहले से मौजूद है या नहीं, तो आप इस तरह से कुछ चला सकते हैं

SELECT 
    1
WHERE
    EXISTS (SELECT * FROM yourTable WHERE [URL] = 'testValue')

यदि आपको नतीजे मिलते हैं तो आप मान सकते हैं कि मूल्य पहले से ही आपके डीबी में कम से कम एक बार मौजूद है।


विशिष्टता की गारंटी के लिए आपको एक अद्वितीय बाधा जोड़ने की आवश्यकता है। अपना टेबल नाम मानना ​​"urls" है और स्तंभ का नाम "url" है, आप इस अलर्ट टेबल कमांड के साथ अद्वितीय बाधा जोड़ सकते हैं:

alter table urls add constraint unique_url unique (url);

यदि तालिका में पहले से ही आपकी तालिका में डुप्लिकेट यूआरएल पहले से मिल चुका है तो संभवतः असफल तालिका (जो वास्तव में MySQL के साथ जानता है)


इस समस्या का समाधान करने पर, आपको पहले यह निर्धारित करना होगा कि आपके प्रोजेक्ट के लिए "डुप्लिकेट URL" का क्या अर्थ है। इससे यह पता चलेगा कि उन्हें डेटाबेस में जोड़ने से पहले यूआरएल को कैनोनिकल बनाने के लिए कैसे करें।

कम से कम दो परिभाषाएं हैं:

  1. दो यूआरएल डुप्लिकेट मानी जाती हैं यदि वे एक ही संसाधन का प्रतिनिधित्व करते हैं जो उस संबंधित वेब सेवा के बारे में कुछ नहीं जानते जिसके बारे में इसी सामग्री को उत्पन्न करता है कुछ विचारों में शामिल हैं:
    • यूआरएल की योजना और डोमेन नाम भाग केस-असंवेदनशील है, इसलिए HTTP://WWW..COM/ http://www..com/ पर समान है।
    • यदि एक URL एक पोर्ट निर्दिष्ट करता है, लेकिन यह योजना के लिए पारंपरिक पोर्ट है और वे अन्यथा समकक्ष हैं, तो वे समान हैं ( http://www..com/ और http://www..com:80 / )
    • अगर क्वेरी स्ट्रिंग में पैरामीटर सरल पुनर्गठन होते हैं और पैरामीटर नाम सभी अलग होते हैं, तो वे समान होते हैं; जैसे कि http: // प्राधिकरण /? ए = परीक्षा और बी = परीक्षा और http: // प्राधिकरण /? बी = परीक्षा और ए = परीक्षा नोट करें कि समानता की पहली परिभाषा के अनुसार http: // प्राधिकरण /? एक% 5 बी% 5 डी = परीक्षा 1 और एक% 5 बी% 5 डी = टेस्ट 2 समान नहीं है, जैसा कि http: // प्राधिकरण /? 5 बी% 5 डी = परीक्षण 2 और एक% 5 बी% 5 डी = टेस्ट 1
    • यदि योजना HTTP या HTTPS है, तो यूआरएल के हैश का भाग हटाया जा सकता है, क्योंकि यूआरएल के इस भाग को वेब सर्वर पर नहीं भेजा जाता है।
    • एक छोटा IPv6 पता विस्तारित किया जा सकता है।
    • यदि केवल अनुपलब्ध है तो केवल अनुगामी आगे की स्लैश में शामिल करें
    • यूनिकोड कैनोनिकीकरण संदर्भित संसाधन को बदलता है; उदाहरण के लिए आप http://google.com/?q=%C3%84 ( %C3%84 यूटीएफ -8 में 'ए' का प्रतिनिधित्व कर सकते हैं) http://google.com/?q = एक% सीसी 88% ( %CC%88 यू + 0308, कॉम्बीनिंग डायएरिज़िस) दर्शाता है।
    • यदि योजना HTTP या HTTPS है, तो ' www. 'यूआरएल के प्राधिकरण में केवल दो यूआरएल अन्यथा बराबर नहीं हटाए जा सकते हैं, क्योंकि डोमेन नाम का पाठ Host HTTP हैडर के मूल्य के रूप में भेजा जाता है, और कुछ वेब सर्वर वर्चुअल मेजबान का उपयोग करने के लिए विभिन्न सामग्री को वापस भेजने के लिए उपयोग करते हैं यह हेडर अधिक सामान्यतः, भले ही डोमेन नाम एक ही आईपी पते पर हल हो, तो आप यह नहीं समझा सकते हैं कि संदर्भित संसाधन समान हैं
  2. मूल यूआरएल कैनोलाइनाइजेशन (उदाहरण के लिए, कम केस, स्कीम और डोमेन नाम, डिफॉल्ट पोर्ट की आपूर्ति, पैरामीटर के नाम से स्थिर सॉर्ट क्वेरी मापदंडों, एचटीटीपी और एचटीटीपीएस के मामले में हैश भाग को हटा दें ...) लागू करें, और इसके बारे में जानकारी लें वेब सेवा हो सकता है कि आप मान लें कि सभी वेब सेवाओं यूनिकोड इनपुट (विकिपीडिया, उदाहरण के लिए) को कैननियकलिज़ करने के लिए पर्याप्त स्मार्ट हैं, ताकि आप यूनिकोड सामान्यीकृत फॉर्म कैननिकल कॉम्प्लेज़ेशन (एनएफसी) लागू कर सकें। आप ' www. ' पट्टी करेंगे 'सभी स्टैक अतिप्रवाह यूआरएल से। आप अनावश्यक यूआरएल के सभी प्रकार के निकालने के लिए पोस्टरैंक की पोस्टरैंक-यूरी कोड का उपयोग कर सकते हैं, जो कि पीएचपी पर रखे गए हैं (जैसे &utm_source=... )।

परिभाषा 1 एक स्थिर समाधान की ओर ले जाता है (यानी कोई और कैननियॉलिकनाइज़ेशन नहीं है जो कि किया जा सकता है और यूआरएल का कैनोनिकलकरण नहीं बदलेगा)। परिभाषा 2, जो मुझे लगता है कि मानव यूआरएल कैननियलाइजेशन की परिभाषा को मानता है, एक कैनोलाइकेलाइजेशन रूटीन की ओर जाता है जो समय के विभिन्न क्षणों पर अलग-अलग परिणाम निकाल सकता है।

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

संपादित करें: यहां तालिका की परिभाषाएं दी गई हैं:

CREATE TABLE `urls1` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `scheme` VARCHAR(20) NOT NULL,
    `canonical_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `canonical_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci', /* the "ci" stands for case-insensitive. Also, we want 'utf8mb4_unicode_ci'
rather than 'utf8mb4_general_ci' because 'utf8mb4_general_ci' treats accented characters as equivalent. */
    `port` INT UNSIGNED,
    `canonical_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    PRIMARY KEY (`id`),
    INDEX (`canonical_host`(10), `scheme`)
) ENGINE = 'InnoDB';


CREATE TABLE `urls2` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `canonical_scheme` VARCHAR(20) NOT NULL,
    `canonical_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `canonical_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `port` INT UNSIGNED,
    `canonical_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    `orig_scheme` VARCHAR(20) NOT NULL, 
    `orig_login` VARCHAR(100) DEFAULT NULL COLLATE 'utf8mb4_bin',
    `orig_host` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_unicode_ci',
    `orig_path` VARCHAR(4096) NOT NULL COLLATE 'utf8mb4_bin',

    PRIMARY KEY (`id`),
    INDEX (`canonical_host`(10), `canonical_scheme`),
    INDEX (`orig_host`(10), `orig_scheme`)
) ENGINE = 'InnoDB';

तालिका `urls1` परिभाषा के अनुसार कैनोनिकल यूआरएल भंडारण के लिए है। तालिका` urls2` परिभाषा 2 के अनुसार कैनोनिकल यूआरएल भंडारण के लिए है।

दुर्भाग्य से आप ट्यूपल (`स्कीम` /` कैनोनिकल_शैमी`, `कैनोनिकल_लॉगिन`,` कैनोनिकल_होस्ट`, `पोर्ट`,` कैनोनिकल_पथ` पर एक UNIQUE प्रतिबंध निर्दिष्ट करने में सक्षम नहीं होंगे) के रूप में MySQL ने InnoDB कुंजी की लंबाई को 767 बाइट्स तक सीमित कर दिया है ।


साधारण एसक्यूएल समाधानों को एक अद्वितीय क्षेत्र की आवश्यकता होती है; तर्क समाधान नहीं करते हैं

आपके यूआरएल को सामान्य बनाना चाहिए ताकि सुनिश्चित हो सके कि कोई दोहराव नहीं है। PHP में फ़ंक्शंस जैसे स्ट्रटोलर () और urldecode () या rawurldecode ()

धारणाएं: आपका टेबल नाम 'वेबसाइट्स' है, आपके url का स्तंभ नाम 'url' है, और यूआरएल के साथ जोड़ा जाने वाला मनमाना डेटा 'डेटा' में है

तर्क समाधान

SELECT COUNT(*) AS UrlResults FROM websites WHERE url='http://www.domain.com'

पिछली प्रश्न का परीक्षण करें यदि एसक्यूएल या PHP में बयानों को यह सुनिश्चित करने के लिए कि यह INSERT स्टेटमेंट के साथ जारी रखने से पहले 0 है।

सरल एसक्यूएल वक्तव्य

परिदृश्य 1: आपका डीबी पहली बार पहली बार सेवा की मेजबानी है और भविष्य में आपको डुप्लिकेट प्रविष्टियों की इच्छा नहीं है।

ALTER TABLE websites ADD UNIQUE (url)

इससे कोई भी प्रविष्टि को डेटाबेस में प्रवेश करने में सक्षम होने से रोकेगा यदि उस कॉलम में यूआरएल मूल्य पहले से मौजूद है।

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

REPLACE INTO websites (url, data) VALUES ('http://www.domain.com', 'random data')

यदि सभी पंक्तियों में एक INSERT के बाद एक पंक्ति मौजूद है, तो यह DELETE कार्रवाई को ट्रिगर करेगा, इसलिए डेली घोषणाओं पर सावधानी बरतें।

INSERT INTO websites (url, data) VALUES ('http://www.domain.com', 'random data')
ON DUPLICATE KEY UPDATE data='random data'

यदि एक पंक्ति मौजूद है और INSERT अगर यह नहीं है, तो यह एक अद्यतन कार्रवाई ट्रिगर करेगा।


पहले, डेटाबेस तैयार करें

  • डोमेन नाम केस-संवेदी नहीं हैं, लेकिन आपको लगता है कि शेष यूआरएल है (यूआरएल में सभी वेब सर्वर का सम्मान नहीं होता है, लेकिन ज्यादातर लोग करते हैं, और आप आसानी से नहीं देख सकते हैं।)
  • मान लें कि आपको एक डोमेन नाम से अधिक स्टोर करने की आवश्यकता है, केस-संवेदी संकेतन का उपयोग करें।
  • यदि आप दो कॉलम में यूआरएल को स्टोर करने का फैसला करते हैं - डोमेन नाम के लिए एक और संसाधन लोकेटर के लिए - डोमेन नाम के लिए केस-असंवेदनशील मिलान का उपयोग करने पर विचार करें, और संसाधन लोकेटर के लिए एक केस-संवेदी कॉलेशन। अगर मैं तुम थे, तो मैं दोनों तरीकों (दो कॉलम में एक कॉलम बनाम यूआरएल में यूआरएल) का परीक्षण करूँगा।
  • यूआरएल कॉलम पर एक अद्वितीय बाधा रखो। या कॉलम की जोड़ी पर, यदि आप डोमेन नाम और संसाधन लोकेटर अलग कॉलम में संग्रहीत करते हैं, तो UNIQUE (url, resource_locator)
  • एन्कोडेड यूआरएल को डेटाबेस से बाहर रखने के लिए एक चेक () बाधा का प्रयोग करें बुरे डेटा को थोक प्रति या एसक्यूएल शेल के माध्यम से आने से रोकने के लिए यह चेक () बाध्यता आवश्यक है।

दूसरा, URL तैयार करें

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

    http://www.amazon.com/Systemantics-Systems-Work-Especially-They/dp/070450331X/ref=sr_1_1?ie=UTF8&qid=1313583998&sr=8-1

    http://www.amazon.com/Systemantics-Systems-Work-Especially-They/dp/070450331X

  • डीकोड एन्कोडेड यूआरएल ( Php के urldecode () फ़ंक्शन देखें । उस पृष्ठ की टिप्पणियों में वर्णित रूप से, अपनी कमियों को सावधानीपूर्वक नोट करें।) निजी तौर पर, मैं क्लाइंट कोड के बजाय डेटाबेस में इन प्रकार के परिवर्तनों को संभालना चाहता हूं। इसमें तालिकाओं और दृश्यों पर अनुमतियों को रद्द करना शामिल है, और केवल सम्मिलित प्रक्रियाओं के माध्यम से आवेषण और अपडेट की अनुमति देता है; संग्रहित प्रक्रिया सभी स्ट्रिंग ऑपरेशन संभालती है जो कि यूके को एक कैनोनिकल फॉर्म में डालती है। लेकिन जब आप कोशिश करते हैं तो प्रदर्शन पर नज़र रखें। चेक () बाधाएं (ऊपर देखें) आपकी सुरक्षा नेट हैं

तीसरा , यदि आप केवल यूआरएल को सम्मिलित कर रहे हैं, तो पहले उसके अस्तित्व का परीक्षण न करें इसके बजाय, उस त्रुटि को सम्मिलित और जाल में डालने का प्रयास करें जो आपको मिलेगा यदि मूल्य पहले से मौजूद है। प्रत्येक नए URL के लिए दो बार डेटाबेस को हिट करने और परीक्षण करने के लिए परीक्षण। सम्मिलित करें-और-जाल बस एक बार डेटाबेस को हिट करता है सावधानीपूर्वक ध्यान दें कि डालें-और-जाल न डालें और अनदेखी-त्रुटियों के समान नहीं है। केवल एक विशेष त्रुटि का अर्थ है कि आप अद्वितीय बाधा का उल्लंघन करते हैं; अन्य त्रुटियों का मतलब है कि अन्य समस्याएं हैं

दूसरी ओर, यदि आप एक ही पंक्ति में कुछ अन्य डेटा के साथ यूआरएल को सम्मिलित कर रहे हैं, तो आपको समय से पहले तय करना होगा कि आप डुप्लिकेट यूआरएल को संभाल लेंगे या नहीं।

प्रतिकृति प्रमुख त्रुटियों को डुप्लिकेट करने की आवश्यकता को समाप्त करता है, लेकिन अगर विदेशी कुंजी संदर्भ होते हैं तो इसका दुर्भाग्यपूर्ण साइड इफेक्ट हो सकता है


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


क्या आप विशुद्ध रूप से यूआरएल के बारे में चिंतित हैं जो सटीक स्ट्रिंग हैं .. यदि ऐसा है तो अन्य उत्तर में बहुत अच्छी सलाह है या आप को भी कैनोनाइजेशन के बारे में चिंता करने की ज़रूरत है?

उदाहरण के लिए: http://google.com और http: //go%4fgle.com सटीक समान यूआरएल हैं, लेकिन डेटाबेस के किसी भी तकनीक द्वारा डुप्लिकेट के रूप में अनुमति दी जाएगी। यदि यह एक समस्या है, तो आपको हल करने के लिए यूआरएल का प्रसंस्करण और चरित्र से बचने वाले दृश्यों को पहले से करना चाहिए।

यह मानते हुए कि आपके द्वारा कौन से यूआरएल आ रहे हैं, उन्हें मापदंडों के बारे में भी चिंतित होना चाहिए और क्या वे आपके आवेदन में महत्वपूर्ण हैं।


यदि आप डुप्लिकेट नहीं करना चाहते हैं तो आप निम्न कर सकते हैं:

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


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

इस कॉलम पर एक अद्वितीय अनुक्रमणिका के साथ एक तालिका बनाने के लिए, आप उपयोग कर सकते हैं

CREATE TABLE MyURLTable(
ID INTEGER NOT NULL AUTO_INCREMENT
,URL VARCHAR(512)
,PRIMARY KEY(ID)
,UNIQUE INDEX IDX_URL(URL)
);

यदि आप सिर्फ एक अद्वितीय बाधा चाहते हैं, और उस तालिका पर कोई सूचकांक नहीं है, तो आप उपयोग कर सकते हैं

CREATE TABLE MyURLTable(
ID INTEGER NOT NULL AUTO_INCREMENT
,URL VARCHAR(512)
,PRIMARY KEY(ID)
,CONSTRAINT UNIQUE UNIQUE_URL(URL)
);

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

ALTER TABLE MyURLTable
ADD UNIQUE INDEX IDX_URL(URL);

ALTER TABLE MyURLTable
ADD CONSTRAINT UNIQUE UNIQUE_URL(URL);

अब, आपके पास पहले से उसमें कुछ डेटा वाला एक टेबल हो सकता है उस स्थिति में, आपके पास पहले से कुछ डुप्लिकेट डेटा हो सकता है आप उपरोक्त दिखाए गए सूचक या सूचक बनाने की कोशिश कर सकते हैं, और यदि आपके पास पहले से ही डुप्लिकेट डेटा है तो यह विफल हो जाएगा। यदि आपके पास डुप्लिकेट डेटा नहीं है, तो महान, यदि आप करते हैं, तो आपको डुप्लिकेट को निकालना होगा। आप निम्नलिखित क्वेरी का उपयोग करते हुए डुप्लिकेट के साथ एक यूआरएल प्रकाशित कर सकते हैं।

SELECT URL,COUNT(*),MIN(ID) 
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) > 1;

डुप्लिकेट वाली पंक्तियों को हटाने के लिए, और एक रखना, निम्न करें:

DELETE RemoveRecords
FROM MyURLTable As RemoveRecords
LEFT JOIN 
(
SELECT MIN(ID) AS ID
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) > 1
UNION
SELECT ID
FROM MyURLTable
GROUP BY URL
HAVING COUNT(*) = 1
) AS KeepRecords
ON RemoveRecords.ID = KeepRecords.ID
WHERE KeepRecords.ID IS NULL;

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

INSERT IGNORE INTO MyURLTable(URL)
VALUES('http://www.example.com');

वह डालने का प्रयास करेगा, और अगर उसे डुप्लिकेट मिल जाए, तो कुछ भी नहीं होगा। अब, कहें कि आपके पास अन्य स्तंभ हैं, आप ऐसा कुछ कर सकते हैं

INSERT INTO MyURLTable(URL,Visits) 
VALUES('http://www.example.com',1)
ON DUPLICATE KEY UPDATE Visits=Visits+1;

वह मान सम्मिलित करने का प्रयास करें, और अगर उसे यूआरएल मिल जाए, तो यह विज़िट काउंटर को बढ़ाकर रिकॉर्ड को अपडेट करेगा। बेशक, आप हमेशा एक सादे पुराने डालने कर सकते हैं, और अपने PHP कोड में परिणामी त्रुटि को संभाल सकते हैं। अब, के लिए या नहीं, आप बाधाओं या अनुक्रमित का उपयोग करना चाहिए, जो बहुत सारे कारकों पर निर्भर करता है। सूचकांक तेजी से देखने के लिए बनाता है, इसलिए आपका प्रदर्शन बेहतर होगा क्योंकि तालिका बड़ी हो जाती है, लेकिन सूचकांक को संचय करने से अतिरिक्त जगह ले जाएगी। इंडेक्स आमतौर पर भी सम्मिलित करते हैं और अपडेट भी लंबे समय तक लेते हैं, क्योंकि उसे सूचकांक अपडेट करना पड़ता है हालांकि, चूंकि वैल्यू को किसी भी तरह से देखा जाना चाहिए, विशिष्टता को लागू करने के लिए, इस मामले में, यह सूचकांक सिर्फ वैसे ही जल्दी हो सकता है। के रूप में कुछ भी प्रदर्शन के लिए संबंधित, जवाब दोनों विकल्पों की कोशिश है और परिणामों को प्रोफ़ाइल देखने के लिए जो आपकी स्थिति के लिए सबसे अच्छा काम करता है


यदि आप तालिका में यूआरएल को सम्मिलित करना चाहते हैं, लेकिन केवल वे मौजूद हैं जो पहले से मौजूद नहीं हैं, तो आप कॉलम पर एक अद्वितीय प्रतिलिपि जोड़ सकते हैं और अपनी INSERT क्वेरी में IGNORE जोड़ सकते हैं ताकि आपको कोई त्रुटि नहीं मिलती।

उदाहरण: INSERT urls SET url = 'यूआरएल-टू-डाइंटर'


अपने शुरुआती प्रश्न का उत्तर देने के लिए, यह जांचने का सबसे आसान तरीका है कि क्या कोई डुप्लिकेट है कि आप SQL क्वेरी चलाने के लिए क्या प्रयास कर रहे हैं उसके खिलाफ है!

उदाहरण के लिए, क्या आप टेबल links में यूआरएल http://www.example.com/ जांच करना चाहते थे, तो आपकी क्वेरी कुछ ऐसा दिखाई देगी

SELECT * FROM links WHERE url = 'http://www.example.com/';

आपका PHP कोड कुछ ऐसा दिखेगा

$conn = mysql_connect('localhost', 'username', 'password');
if (!$conn)
{
    die('Could not connect to database');
}
if(!mysql_select_db('mydb', $conn))
{
    die('Could not select database mydb');
}

$result = mysql_query("SELECT * FROM links WHERE url = 'http://www.example.com/'", $conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    die('This URL already exists in the database');
}

मैंने इसे यहां तक ​​सीमित रखा है, यहां तक ​​कि सभी डेटाबेस से कनेक्ट होने आदि। यह संभव है कि आपके पास पहले से एक डेटाबेस से कनेक्शन होगा, इसलिए आपको इसका उपयोग करना चाहिए कि एक नया कनेक्शन शुरू करने के बजाय ( $conn जगह mysql_query कमांड और mysql_connect और mysql_select_db साथ करने के लिए सामान को हटा दें)

बेशक, डेटाबेस से कनेक्ट करने के अन्य तरीके हैं, जैसे पीडीओ, या एक ओआरएम या इसी तरह का उपयोग करना, इसलिए यदि आप पहले से ही उन का उपयोग कर रहे हैं, तो यह जवाब प्रासंगिक नहीं हो सकता है (और यह संभवतः दायरा से परे है इस से संबंधित उत्तर यहाँ!)

हालांकि, MySQL पहली जगह में होने से इसे रोकने के कई तरीके प्रदान करता है

सबसे पहले, आप एक फ़ील्ड को "अद्वितीय" के रूप में चिह्नित कर सकते हैं

चलिए कहते हैं कि मेरे पास एक टेबल है जहां मैं सिर्फ उन सभी यूआरएलों को जमा करना चाहता हूं जो मेरी साइट से जुड़े हुए हैं, और आखिरी बार उनका दौरा किया गया था।

मेरी परिभाषा इस तरह से कुछ दिखाई दे सकती है: -

CREATE TABLE links
(
    url VARCHAR(255) NOT NULL,
    last_visited TIMESTAMP
)

इससे मुझे एक ही यूआरएल को बार-बार जोड़ने की इजाजत मिलेगी, जब तक कि मैं इसके बाद के संस्करण के समान कुछ PHP कोड लिखने को रोकूं।

हालांकि, मेरी परिभाषा में बदलना था

CREATE TABLE links
(
  url VARCHAR(255)  NOT NULL,
  last_visited TIMESTAMP,
  PRIMARY KEY (url)
)

तब यह mysql को एक त्रुटि फेंक देगा जब मैंने समान मूल्य को दो बार सम्मिलित करने का प्रयास किया।

PHP में एक उदाहरण होगा

$result = mysql_query("INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW()", $conn);

if (!$result)
{
    die('Could not Insert Row 1');
}

$result2 = mysql_query("INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW()", $conn);

if (!$result2)
{
    die('Could not Insert Row 2');
}

यदि आप इसे चलाते हैं, तो आप पाएंगे कि पहले प्रयास पर, स्क्रिप्ट टिप्पणी के साथ मर जाएगी Could not Insert Row 2 हालांकि, बाद के रनों पर, यह मर गया था, साथ में Could not Insert Row 1 किया Could not Insert Row 1

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

CREATE TABLE users (
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40) NOT NULL,
  PRIMARY KEY (username)
)

हालांकि, जब हम उपयोगकर्ता द्वारा बनाई गई पोस्ट के बारे में जानकारी संग्रहीत करना चाहते थे, तो हमें उस पद के उपयोगकर्ता नाम को उस पहचानने के लिए संग्रहित करना होगा, जिसकी पहचान उस पद के उस उपयोगकर्ता से हुई थी।

मैंने पहले ही उल्लेख किया है कि माईएसक्यूएल तारों की तुलना में संख्याओं को देखने में तेजी से है, इसलिए इसका मतलब यह होगा कि जब हमें ऐसा करने की ज़रूरत नहीं थी तब हम तारों को देखने में समय व्यतीत करेंगे।

इसे सुलझाने के लिए, हम एक अतिरिक्त कॉलम, यूज़र_आईडी जोड़ सकते हैं और प्राथमिक कुंजी बना सकते हैं (इसलिए जब किसी पोस्ट के आधार पर यूजर रिकॉर्ड की तलाश की जाती है, तो हम इसे शीघ्र खोज सकते हैं)

CREATE TABLE users (
  user_id INT(10)  NOT NULL AUTO_INCREMENT,
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40)  NOT NULL,
  PRIMARY KEY (`user_id`)
)

आप देखेंगे कि मैंने यहां कुछ नया जोड़ा है - AUTO_INCREMENT। यह मूल रूप से हमें उस क्षेत्र की स्वयं की देखभाल करने की अनुमति देता है हर बार एक नई पंक्ति डाली जाती है, यह 1 को पिछली संख्या में जोड़ती है, और यह स्टोर करता है, इसलिए हमें नंबरिंग के बारे में चिंता करने की ज़रूरत नहीं है, और यह इसे स्वयं ही करने देता है

तो, उपरोक्त तालिका के साथ, हम कुछ ऐसा कर सकते हैं

INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');

और फिर

INSERT INTO users (username, password) VALUES('User', '988881adc9fc3655077dc2d4d757d480b5ea0e11');

जब हम डेटाबेस से रिकॉर्ड का चयन करते हैं, तो हमें निम्नलिखित प्राप्त होता है: -

mysql> SELECT * FROM users;
+---------+----------+------------------------------------------+
| user_id | username | password                                 |
+---------+----------+------------------------------------------+
|       1 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
|       2 | User     | 988881adc9fc3655077dc2d4d757d480b5ea0e11 |
+---------+----------+------------------------------------------+
2 rows in set (0.00 sec)

हालांकि, यहां - हमारे पास एक समस्या है - हम अभी भी उसी उपयोगकर्ता नाम के साथ दूसरे उपयोगकर्ता जोड़ सकते हैं! जाहिर है, यह ऐसा कुछ है जिसे हम करना नहीं चाहते हैं!

mysql> SELECT * FROM users;
+---------+----------+------------------------------------------+
| user_id | username | password                                 |
+---------+----------+------------------------------------------+
|       1 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
|       2 | User     | 988881adc9fc3655077dc2d4d757d480b5ea0e11 |
|       3 | Mez      | d3571ce95af4dc281f142add33384abc5e574671 |
+---------+----------+------------------------------------------+
3 rows in set (0.00 sec)

हमारी तालिका परिभाषा बदलने की सुविधा देता है!

CREATE TABLE users (
  user_id INT(10)  NOT NULL AUTO_INCREMENT,
  username VARCHAR(255)  NOT NULL,
  password VARCHAR(40)  NOT NULL,
  PRIMARY KEY (user_id),
  UNIQUE KEY (username)
)

देखते हैं कि जब हम एक ही उपयोगकर्ता को दो बार कोशिश करते हैं और सम्मिलित करते हैं तो क्या होता है।

mysql> INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO users (username, password) VALUES('Mez', 'd3571ce95af4dc281f142add33384abc5e574671');
ERROR 1062 (23000): Duplicate entry 'Mez' for key 'username'

हुज़्ज़ाह !! हम अब एक त्रुटि प्राप्त करते हैं जब हम दूसरे समय के लिए यूज़रनेम की कोशिश करते हैं और डालें। ऊपर की तरह कुछ का उपयोग करना, हम इसे PHP में पता लगा सकते हैं

अब, हमारे लिंक तालिका में वापस जाने दें, लेकिन एक नई परिभाषा के साथ।

CREATE TABLE links
(
    link_id INT(10)  NOT NULL AUTO_INCREMENT,
    url VARCHAR(255)  NOT NULL,
    last_visited TIMESTAMP,
    PRIMARY KEY (link_id),
    UNIQUE KEY (url)
)

और डेटाबेस में "http://www.example.com" डालें।

INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());

अगर हम कोशिश करते हैं और इसे फिर से डालें ...

ERROR 1062 (23000): Duplicate entry 'http://www.example.com/' for key 'url'

लेकिन अगर हम उस समय का अद्यतन करना चाहते हैं तो यह क्या होगा?

ठीक है, हम PHP के साथ जटिल कुछ कर सकते हैं, जैसे: -

$result = mysql_query("SELECT * FROM links WHERE url = 'http://www.example.com/'", $conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    $result = mysql_query("UPDATE links SET last_visited = NOW() WHERE url = 'http://www.example.com/'", $conn);

    if (!$result)
    {
        die('There was a problem updating the links table');
    }
}

या, यहां तक ​​कि डेटाबेस में पंक्ति का आईडी पकड़ कर उसे अद्यतन करने के लिए उपयोग करें।

$ परिणाम = mysql_query ("चुनें * लिंक से WHERE url = 'http://www.example.com/', $ conn);

if (!$result)
{
    die('There was a problem executing the query');
}

$number_of_rows = mysql_num_rows($result);

if ($number_of_rows > 0)
{
    $row = mysql_fetch_assoc($result);

    $result = mysql_query('UPDATE links SET last_visited = NOW() WHERE link_id = ' . intval($row['link_id'], $conn);

    if (!$result)
    {
        die('There was a problem updating the links table');
    }
}

लेकिन, MySQL में एक अच्छी तरह से निर्मित सुविधा है जिसे REPLACE INTO में बुलाया गया है

देखते हैं कि यह कैसे काम करता है।

mysql> SELECT * FROM links;
+---------+-------------------------+---------------------+
| link_id | url                     | last_visited        |
+---------+-------------------------+---------------------+
|       1 | http://www.example.com/ | 2011-08-19 23:48:03 |
+---------+-------------------------+---------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());
ERROR 1062 (23000): Duplicate entry 'http://www.example.com/' for key 'url'
mysql> REPLACE INTO links (url, last_visited) VALUES ('http://www.example.com/', NOW());
Query OK, 2 rows affected (0.00 sec)

mysql> SELECT * FROM links;
+---------+-------------------------+---------------------+
| link_id | url                     | last_visited        |
+---------+-------------------------+---------------------+
|       2 | http://www.example.com/ | 2011-08-19 23:55:55 |
+---------+-------------------------+---------------------+
1 row in set (0.00 sec)

ध्यान दें कि जब में प्रतिस्थापन का उपयोग करते हुए, यह अंतिम_दृश्य समय को अपडेट करता है, और कोई त्रुटि नहीं डालती है!

इसका कारण यह है कि MySQL पता लगाता है कि आप एक पंक्ति को बदलने का प्रयास कर रहे हैं यह वह पंक्ति जानता है जिसे आप चाहते हैं, क्योंकि आपने यूआरएल को अद्वितीय बनाने के लिए सेट किया है MySQL आपके द्वारा पारित बिट का उपयोग करके प्रतिस्थापित करने के लिए पंक्ति को बताता है कि वह अद्वितीय होना चाहिए (इस मामले में, यूआरएल) और उस पंक्ति के लिए अन्य मूल्यों को अद्यतन करना। यह link_id भी अपडेट किया गया है - जो थोड़ा अप्रत्याशित है! (वास्तव में, मुझे नहीं पता था कि ऐसा तब तक होता जब तक मैंने ऐसा नहीं देखा!)

लेकिन क्या होगा अगर आप एक नया यूआरएल जोड़ना चाहते हैं? खैर, यदि कोई मिलान वाली अनूठी पंक्ति नहीं मिल पाती है, तो फिर से एक नए पंक्ति को खुशी से REPLACE INTO देगा!

mysql> REPLACE INTO links (url, last_visited) VALUES ('http://www..com/', NOW());
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM links;
+---------+-------------------------------+---------------------+
| link_id | url                           | last_visited        |
+---------+-------------------------------+---------------------+
|       2 | http://www.example.com/       | 2011-08-20 00:00:07 |
|       3 | http://www..com/ | 2011-08-20 00:01:22 |
+---------+-------------------------------+---------------------+
2 rows in set (0.00 sec)

मुझे उम्मीद है कि यह आपके प्रश्न का उत्तर देगा, और आपको MySQL के काम के बारे में कुछ और जानकारी प्रदान करता है!


स्तंभ को primary key बनाओ





mysql