MySQL में सरणियों को कैसे स्टोर करें?


118

मेरे पास MySQL में दो टेबल हैं। तालिका व्यक्ति के निम्नलिखित कॉलम हैं:

id | name | fruits

fruitsस्तंभ नल या ( 'सेब', 'नारंगी', 'केला'), या ( 'स्ट्रॉबेरी'), आदि दूसरी तालिका तालिका फल है और निम्नलिखित तीन कॉलम है की तरह तार की एक सरणी पकड़ सकता है:

____________________________
fruit_name | color  | price
____________________________
apple      | red    | 2
____________________________
orange     | orange | 3
____________________________
...,...

तो मुझे fruitsपहली तालिका में कॉलम को कैसे डिज़ाइन करना चाहिए ताकि यह fruit_nameदूसरी तालिका में कॉलम से मान लेने वाले स्ट्रिंग की सरणी पकड़ सके ? चूंकि MySQL में कोई सरणी डेटा प्रकार नहीं है, मुझे यह कैसे करना चाहिए?



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

@JanusTroelsen: मैं DB पढ़ने / लिखने के लिए PHP का उपयोग नहीं कर रहा हूँ। तो क्या इसे करने का एक सार्वभौमिक तरीका है?
टोंगा

1
@ टोंगा मेरी बेला की जाँच करें कि आप क्या चाहते हैं?
echo_Me

जवाबों:


163

ऐसा करने का उचित तरीका है कि JOINआप अपने प्रश्नों में कई तालिकाओं और उनका उपयोग करें।

उदाहरण के लिए:

CREATE TABLE person (
`id` INT NOT NULL PRIMARY KEY,
`name` VARCHAR(50)
);

CREATE TABLE fruits (
`fruit_name` VARCHAR(20) NOT NULL PRIMARY KEY,
`color` VARCHAR(20),
`price` INT
);

CREATE TABLE person_fruit (
`person_id` INT NOT NULL,
`fruit_name` VARCHAR(20) NOT NULL,
PRIMARY KEY(`person_id`, `fruit_name`)
);

person_fruitतालिका प्रत्येक फल एक व्यक्ति के साथ जुड़ा हुआ है के लिए एक पंक्ति में शामिल है और प्रभावी ढंग से लिंक personऔर fruitsटेबल एक साथ, आईई

1 | "banana"
1 | "apple"
1 | "orange"
2 | "straberry"
2 | "banana"
2 | "apple"

जब आप किसी व्यक्ति और उनके सभी फलों को पुनः प्राप्त करना चाहते हैं, तो आप कुछ ऐसा कर सकते हैं:

SELECT p.*, f.*
FROM person p
INNER JOIN person_fruit pf
ON pf.person_id = p.id
INNER JOIN fruits f
ON f.fruit_name = pf.fruit_name

4
तीसरी तालिका व्यक्ति और फल के बीच की कड़ी तालिका है। तो अगर किसी व्यक्ति के पास 100 फल हैं। मुझे तीसरी तालिका में 100 पंक्तियाँ बनाने की आवश्यकता है, है ना? क्या यह कुशल है?
टोंगा

1
@ टोंगा वास्तव में, 100 पंक्तियों में से प्रत्येक में person_idएक ही होगा लेकिन एक अलग fruit_name। यह प्रभावी रूप से जानूस के उत्तर से सिद्धांत का कार्यान्वयन है।
खराब वुल्फ

1
क्या यह हमेशा सच है कि दो तालिकाओं के बीच किसी भी संबंध को तीसरे तालिका में संग्रहीत करने की आवश्यकता है? क्या मैं केवल दो तालिकाओं से प्राथमिक कुंजी संग्रहीत करके संबंध खोजने के लिए क्वेरी कर सकता हूं?
टोंगा २

2
हां, उदाहरण के लिए अब सेटअप कैसे किया जाता है। व्यक्ति के बारे में कोई भी जानकारी personतालिका में होनी चाहिए, तालिका में फल के बारे में fruitsकोई भी जानकारी और विशेष रूप से किसी व्यक्ति और person_fruitतालिका में किसी विशेष फल के बीच संबंध के बारे में कोई भी जानकारी । क्योंकि इस उदाहरण में कोई अतिरिक्त जानकारी नहीं है person_fruitतालिका केवल दो कॉलम है, प्राथमिक कुंजी personऔर fruitsतालिकाओं की। एक विशिष्ट फल की मात्रा कुछ और का एक उदाहरण है जो person_fruitहालांकि तालिका में जा सकता है ।
बुरा वुल्फ

2
क्या यह INTएक कुंजी के लिए उपयोग करना बेहतर नहीं होगा fruitsऔर केवल इसमें INTहै person_fruit? इसलिए बाद में नाम बदला जा सकता है और आपको कम जगह की भी आवश्यकता होगी यदि आपके पास इनकी fruitsतुलना में बहुत अधिक पंक्तियाँ नहीं हैं person_fruit
12431234123412341234123

58

कारण यह है कि SQL में कोई सरणियाँ नहीं हैं, ऐसा इसलिए है क्योंकि अधिकांश लोगों को वास्तव में इसकी आवश्यकता नहीं है। संबंधपरक डेटाबेस (SQL वास्तव में है) संबंधों का उपयोग करके काम करते हैं, और अधिकांश समय, यह सबसे अच्छा है यदि आप प्रत्येक "जानकारी के लिए" तालिका की एक पंक्ति असाइन करते हैं। उदाहरण के लिए, जहां आप सोच सकते हैं कि "मुझे यहां सामान की एक सूची पसंद है", इसके बजाय एक नई तालिका बनाएं, पंक्ति को दूसरी तालिका में पंक्ति के साथ एक तालिका में लिंक करें। [1] इस तरह, आप M: N संबंधों का प्रतिनिधित्व कर सकते हैं। एक और लाभ यह है कि उन लिंक पंक्तिबद्ध आइटम से अव्यवस्थित नहीं होंगे। और डेटाबेस उन पंक्तियों को अनुक्रमित कर सकता है। ऐरे आमतौर पर अनुक्रमित नहीं होते हैं।

यदि आपको रिलेशनल डेटाबेस की आवश्यकता नहीं है, तो आप उदाहरण के लिए एक की-वैल्यू स्टोर का उपयोग कर सकते हैं।

कृपया डेटाबेस सामान्यीकरण के बारे में पढ़ें । सुनहरा नियम "[हर] गैर-कुंजी [विशेषता] कुंजी, संपूर्ण कुंजी, और लेकिन कुंजी के बारे में एक तथ्य प्रदान करना चाहिए।" एक सरणी बहुत अधिक है। इसके कई तथ्य हैं और यह ऑर्डर को संग्रहीत करता है (जो स्वयं संबंधित नहीं है)। और प्रदर्शन खराब है (ऊपर देखें)।

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

[१]: यह ठीक है यदि लिंकिंग टेबल में केवल दो कॉलम हैं (प्रत्येक टेबल से प्राथमिक कुंजी)! यदि रिश्ते में अतिरिक्त विशेषताएं हैं, तो भी उन्हें स्तंभ के रूप में इस तालिका में दर्शाया जाना चाहिए।


2
धन्यवाद जानूस यह समझ आता है। अब मुझे समझ में आया कि MySQL एक कॉलम में सरणी प्रकार का समर्थन क्यों नहीं करता है।
टोंगा

2
@Sai - मैं जो सामान कर रहा हूं, क्या मुझे वास्तव में NoSQL समाधान की आवश्यकता है?
टोंगा

1
ठीक है, इसलिए यदि मेरे पास एक मेज है जिसमें एक क्षेत्र में हजारों तत्वों का एक संख्यात्मक सरणी है, उदाहरण के लिए, एक सेंसर से एकत्र किए गए कुछ 2D डेटा, क्या NoSQL DB का उपयोग करना बेहतर है?
टोंगा

5
@ टोंगा: डेटा की मात्रा उपयोग करने के लिए db प्रकार का निर्धारण नहीं करती है, डेटा की प्रकृति करती है। यदि कोई संबंध नहीं हैं, तो आपको संबंधपरक डेटाबेस की आवश्यकता नहीं है। लेकिन चूंकि यह उद्योग मानक है, आप इसे रख सकते हैं और सिर्फ संबंधपरक सुविधाओं का उपयोग नहीं कर सकते हैं। अधिकांश डेटा किसी तरह से संबंधपरक है! संबंधपरक डेटाबेसों को निरूपित करने या कुंजी-मूल्य स्टोर का उपयोग करने का एक सामान्य कारण प्रदर्शन कारणों से है। लेकिन वे समस्याएँ केवल एक बार उठती हैं जब आपके पास लाखों पंक्तियाँ होती हैं! समय से पहले अनुकूलन मत करो! मैं सिर्फ एक SQL db (मैं PostgreSQL की सलाह देता हूं) के साथ जा रहा हूं। यदि आपको समस्या है, तो पूछें।
19us में Janus Troelsen

2
PostgreSQL में कुंजी-मूल्य वाले स्टोर भी हैं, जिसका अर्थ है कि यदि आप फिट नहीं होते हैं, तो रिलेशनल मॉडल से दूर जाना आसान होगा।
जानूस ट्रॉल्सन

50

MySQL 5.7 अब एक JSON डेटा प्रकार प्रदान करता है । यह नया डेटाटाइप जटिल डेटा को स्टोर करने के लिए एक सुविधाजनक नया तरीका प्रदान करता है: सूची, शब्दकोश, आदि।

उस ने कहा, rrays डेटाबेस को अच्छी तरह से मैप नहीं करता है, यही वजह है कि ऑब्जेक्ट-रिलेशनल मैप्स काफी जटिल हो सकते हैं। ऐतिहासिक रूप से लोगों ने MySQL में सूचियाँ / सरणियाँ संग्रहीत की हैं, जिसमें एक तालिका बनाकर उनका वर्णन किया गया है और प्रत्येक मूल्य को अपने रिकॉर्ड के रूप में जोड़ा गया है। तालिका में केवल 2 या 3 कॉलम हो सकते हैं, या इसमें कई और भी हो सकते हैं। आप इस प्रकार के डेटा को कैसे संग्रहीत करते हैं यह वास्तव में डेटा की विशेषताओं पर निर्भर करता है।

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

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


43

एक विचार करने के लिए, आप पोस्टग्रेज में सरणियों को स्टोर कर सकते हैं।


6
अतिरिक्त ध्यान दें: उन्हें अनुक्रमित किया जा सकता है, इसलिए किसी सरणी में विशिष्ट मूल्यों के अस्तित्व के लिए जांच करने वाले प्रश्न बहुत तेज़ हो सकते हैं। समान जटिल JSON प्रकारों के लिए जाता है।
टाइमऑफली

5
यह किसी भी तरह से सवाल का जवाब नहीं देता है। ओपी ने MySQL के बारे में पूछा।
झपट्ट

1
यदि आप Postgres में ArrayField का उपयोग करते हैं और उस कॉलम में मानों की एक विस्तृत सूची होती है (जैसे टैग की एक निश्चित सूची), तो आप GIN इंडेक्स बना सकते हैं - यह नाटकीय रूप से उस कॉलम पर प्रश्नों को गति देगा।
lumos42

25

MySQL में, JSON प्रकार का उपयोग करें।

उपरोक्त उत्तरों के विपरीत, SQL मानक में लगभग बीस वर्षों के लिए सरणी प्रकार शामिल हैं; वे उपयोगी होते हैं, भले ही MySQL ने उन्हें लागू नहीं किया हो।

हालाँकि, आपके उदाहरण में, आप संभवतः तीन तालिकाएँ बनाना चाहेंगे: व्यक्ति और फल, फिर उनसे जुड़ने के लिए person_fruit।

DROP TABLE IF EXISTS person_fruit;
DROP TABLE IF EXISTS person;
DROP TABLE IF EXISTS fruit;

CREATE TABLE person (
  person_id   INT           NOT NULL AUTO_INCREMENT,
  person_name VARCHAR(1000) NOT NULL,
  PRIMARY KEY (person_id)
);

CREATE TABLE fruit (
  fruit_id    INT           NOT NULL AUTO_INCREMENT,
  fruit_name  VARCHAR(1000) NOT NULL,
  fruit_color VARCHAR(1000) NOT NULL,
  fruit_price INT           NOT NULL,
  PRIMARY KEY (fruit_id)
);

CREATE TABLE person_fruit (
  pf_id     INT NOT NULL AUTO_INCREMENT,
  pf_person INT NOT NULL,
  pf_fruit  INT NOT NULL,
  PRIMARY KEY (pf_id),
  FOREIGN KEY (pf_person) REFERENCES person (person_id),
  FOREIGN KEY (pf_fruit) REFERENCES fruit (fruit_id)
);

INSERT INTO person (person_name)
VALUES
  ('John'),
  ('Mary'),
  ('John'); -- again

INSERT INTO fruit (fruit_name, fruit_color, fruit_price)
VALUES
  ('apple', 'red', 1),
  ('orange', 'orange', 2),
  ('pineapple', 'yellow', 3);

INSERT INTO person_fruit (pf_person, pf_fruit)
VALUES
  (1, 1),
  (1, 2),
  (2, 2),
  (2, 3),
  (3, 1),
  (3, 2),
  (3, 3);

यदि आप किसी व्यक्ति को फलों के एक समूह के साथ जोड़ना चाहते हैं, तो आप ऐसा कर सकते हैं:

DROP VIEW IF EXISTS person_fruit_summary;
CREATE VIEW person_fruit_summary AS
  SELECT
    person_id                                                                                              AS pfs_person_id,
    max(person_name)                                                                                       AS pfs_person_name,
    cast(concat('[', group_concat(json_quote(fruit_name) ORDER BY fruit_name SEPARATOR ','), ']') as json) AS pfs_fruit_name_array
  FROM
    person
    INNER JOIN person_fruit
      ON person.person_id = person_fruit.pf_person
    INNER JOIN fruit
      ON person_fruit.pf_fruit = fruit.fruit_id
  GROUP BY
    person_id;

दृश्य निम्नलिखित डेटा दिखाता है:

+---------------+-----------------+----------------------------------+
| pfs_person_id | pfs_person_name | pfs_fruit_name_array             |
+---------------+-----------------+----------------------------------+
|             1 | John            | ["apple", "orange"]              |
|             2 | Mary            | ["orange", "pineapple"]          |
|             3 | John            | ["apple", "orange", "pineapple"] |
+---------------+-----------------+----------------------------------+

5.7.22 में, आप स्ट्रिंग से एक साथ सरणी को हैक करने के बजाय JSON_ARRAYAGG का उपयोग करना चाहेंगे ।


2

सरणियों को संग्रहीत करने के लिए डेटाबेस फ़ील्ड प्रकार BLOB का उपयोग करें।

Ref: http://us.php.net/manual/en/function.serialize.php

वापसी मान

एक स्ट्रिंग देता है जिसमें मूल्य का बाइट-स्ट्रीम प्रतिनिधित्व होता है जिसे कहीं भी संग्रहीत किया जा सकता है।

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


-4

आप उस तरह group_Concat का उपयोग करके अपने सरणी को संग्रहीत कर सकते हैं

 INSERT into Table1 (fruits)  (SELECT GROUP_CONCAT(fruit_name) from table2)
 WHERE ..... //your clause here

यहाँ बेला में एक उदाहरण है


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