Mysql
 sql >> डेटाबेस >  >> RDS >> Mysql

MySQL - सीमांकक से अलग किए गए आईडी वाले कॉलम को सामान्य कैसे करें

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

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

इस उदाहरण के लिए डेटा सेटअप करने के लिए, मैंने इस संरचना का उपयोग किया:

CREATE TABLE notnormal_customers (
  id INT NOT NULL PRIMARY KEY,
  aliases VARCHAR(10)
);

INSERT INTO notnormal_customers (id,aliases)
VALUES
(1,'|4|58|76'),
(2,''),
(3,''),
(4,'|1|58|76'),
(58,'|1|4|76'),
(76,'|1|4|58');

सबसे पहले, एक-से-अनेक संबंध का प्रतिनिधित्व करने के लिए एक-ग्राहक से अनेक-उपनामों का प्रतिनिधित्व करने के लिए, मैंने यह तालिका बनाई:

CREATE TABLE customer_aliases (
    primary_id INT NOT NULL,
    alias_id INT NOT NULL,
    FOREIGN KEY (primary_id) REFERENCES notnormal_customers(id),
    FOREIGN KEY (alias_id)   REFERENCES notnormal_customers(id),
    /* clustered primary key prevents duplicates */
    PRIMARY KEY (primary_id,alias_id)
)

सबसे महत्वपूर्ण बात, हम एक कस्टम SPLIT_STR समारोह :

CREATE FUNCTION SPLIT_STR(
  x VARCHAR(255),
  delim VARCHAR(12),
  pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
       LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
       delim, '');

फिर हम सभी काम करने के लिए एक संग्रहित प्रक्रिया तैयार करेंगे। स्रोत संदर्भों पर टिप्पणियों के साथ कोड की व्याख्या की जाती है।

DELIMITER $$
CREATE PROCEDURE normalize_customers()
BEGIN

  DECLARE cust_id INT DEFAULT 0;
  DECLARE al_id INT UNSIGNED DEFAULT 0;
  DECLARE alias_str VARCHAR(10) DEFAULT '';
  /* set the value of the string delimiter */
  DECLARE string_delim CHAR(1) DEFAULT '|';
  DECLARE count_aliases INT DEFAULT 0;
  DECLARE i INT DEFAULT 1;

  /*
    use cursor to iterate through all customer records
    http://burnignorance.com/mysql-tips/how-to-loop-through-a-result-set-in-mysql-strored-procedure/
  */
  DECLARE done INT DEFAULT 0;
  DECLARE cur CURSOR FOR
      SELECT `id`, `aliases`
      FROM `notnormal_customers`;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN cur;
  read_loop: LOOP

    /*
      Fetch one record from CURSOR and set to customer id and alias string.
      If not found then `done` will be set to 1 by continue handler.
    */
    FETCH cur INTO cust_id, alias_str;
    IF done THEN
        /* If done set to 1 then exit the loop, else continue. */
        LEAVE read_loop;
    END IF;

    /* skip to next record if no aliases */
    IF alias_str = '' THEN
      ITERATE read_loop;
    END IF;

    /*
      get number of aliases
      https://pisceansheart.wordpress.com/2008/04/15/count-occurrence-of-character-in-a-string-using-mysql/
    */
    SET count_aliases = LENGTH(alias_str) - LENGTH(REPLACE(alias_str, string_delim, ''));

    /* strip off the first pipe to make it compatible with our SPLIT_STR function */
    SET alias_str = SUBSTR(alias_str, 2);

    /*
      iterate and get each alias from custom split string function
      https://stackoverflow.com/questions/18304857/split-delimited-string-value-into-rows
    */
    WHILE i <= count_aliases DO

      /* get the next alias id */
      SET al_id = CAST(SPLIT_STR(alias_str, string_delim, i) AS UNSIGNED);
      /* REPLACE existing values instead of insert to prevent errors on primary key */
      REPLACE INTO customer_aliases (primary_id,alias_id) VALUES (cust_id,al_id);
      SET i = i+1;

    END WHILE;
    SET i = 1;

  END LOOP;
  CLOSE cur;

END$$
DELIMITER ;

अंत में आप इसे कॉल करके आसानी से चला सकते हैं:

CALL normalize_customers();

फिर आप कंसोल में डेटा की जांच कर सकते हैं:

mysql> select * from customer_aliases;
+------------+----------+
| primary_id | alias_id |
+------------+----------+
|          4 |        1 |
|         58 |        1 |
|         76 |        1 |
|          1 |        4 |
|         58 |        4 |
|         76 |        4 |
|          1 |       58 |
|          4 |       58 |
|         76 |       58 |
|          1 |       76 |
|          4 |       76 |
|         58 |       76 |
+------------+----------+
12 rows in set (0.00 sec)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. mysqli_query को निष्पादित करने में समस्या आ रही है

  2. सभी तालिकाओं के लिए सभी प्रश्नों के लिए हाइबरनेट में सामान्य मानदंड प्रतिबंध

  3. MySql त्रुटि:1364 फ़ील्ड 'display_name' का डिफ़ॉल्ट मान नहीं है

  4. डोकर-लिखें की mariadb परिवर्तन के बाद रिबूट नहीं कर सकता (निकास कोड 1)

  5. mysql में एक कॉलम में शीर्ष 10 सबसे अधिक होने वाले मानों की गणना करें