MySQL: क्यों Auto_increment सिर्फ प्राथमिक कुंजी तक सीमित है?


10

मुझे पता है कि MySQL प्राथमिक कुंजियों में auto_increment कॉलम को सीमित करता है। ऐसा क्यों है? मेरा पहला विचार यह है कि यह एक प्रदर्शन प्रतिबंध है, क्योंकि शायद कुछ काउंटर टेबल कहीं है जो इस मूल्य को प्राप्त करने के लिए लॉक होना चाहिए।

मेरे पास एक ही तालिका में एकाधिक auto_increment कॉलम क्यों नहीं हो सकते?

धन्यवाद।


मैंने अभी देखा कि मैं लेन-देन में @pop का उपयोग करना भूल गया। मैंने उदाहरण दिया और अपने उत्तर के नीचे इसे पोस्ट किया !!!
रोलैंडमाइसीडीडीबीए

मुझे यह सवाल पसंद है क्योंकि यह मुझे MySQL के साथ बॉक्स से बाहर निकलने के बारे में सोच रहा है जो मैं शुक्रवार रात को बहुत ज्यादा नहीं करता हूं। +1 !!!
रोलैंडमाइसीडीडीबीए

जवाबों:


9

आप एक ऐसा स्वतः-कॉलम क्यों चाहते हैं जो प्राथमिक कुंजी नहीं है?

यदि आप चाहते हैं कि कोई कॉलम स्वतः_संचालित हो, तो परिभाषा के अनुसार, आप उस कॉलम में सार्थक डेटा संग्रहीत नहीं कर रहे हैं। एकमात्र मामला जहां गैर-सार्थक जानकारी संग्रहीत करना समझ में आता है वह विशेष मामला है जिसे आप सिंथेटिक प्राथमिक कुंजी रखना चाहते हैं। उस स्थिति में, जानकारी की कमी एक लाभ है क्योंकि इसमें कोई जोखिम नहीं है कि कोई व्यक्ति भविष्य में कभी भी साथ आएगा और डेटा बदलना चाहेगा क्योंकि कुछ इकाई के कुछ गुणधर्म बदल गए।

एक ही तालिका में कई auto_increment कॉलम होने से यह और भी अजीब लगता है। दो स्तंभों में एक ही डेटा होगा - वे एक ही एल्गोरिदम द्वारा उत्पन्न किए जा रहे हैं और एक ही समय में सभी के बाद आबादी वाले हैं। मुझे लगता है कि आप एक कार्यान्वयन के साथ आ सकते हैं जहां उनके लिए समवर्ती से थोड़ा बाहर होना संभव है यदि पर्याप्त समवर्ती सत्र थे। लेकिन मैं कल्पना नहीं कर सकता कि यह कैसे एक आवेदन में कभी उपयोगी होगा।


यह एक सैद्धांतिक सवाल था - मेरे पास कई ऑटो_इंक्रिमेंट कॉलम होने का कोई व्यावहारिक उपयोग नहीं है, मैं सिर्फ लोगों के स्पष्टीकरणों को सुनना चाहता था क्योंकि यह क्यों संभव नहीं था। जवाब देने में व़क्त लेने के लिए शुक्रिया! :)
क्रिस्टोफर आर्मस्ट्रांग

2
"आप ऐसा स्वतः-कॉलम क्यों चाहते हैं जो प्राथमिक कुंजी नहीं है?" - मैं व्यक्तिगत रूप से कुछ कारणों के बारे में सोच सकता हूं। लेकिन वह ओटी है। :-)
डेनिस डी बर्नार्डी

मैं अब ऐसा कुछ कर रहा हूं - और यह अर्थहीन डेटा नहीं है। मुझे एक तालिका में सम्मिलित किए गए सभी रिकॉर्ड की एक संख्या जानने की आवश्यकता है, लेकिन पहले से ही अधिक उपयोगी प्राथमिक कुंजी है। यह हल करता है कि, जैसा कि हर नए रिकॉर्ड का मूल्य होता है। एक (कमजोर) सादृश्य "आप हमारे 10,000 वें ग्राहक होंगे" आवश्यकता होगी। ग्राहक समय के साथ नष्ट हो जाते हैं, इसलिए COUNT (*) मान्य नहीं है।
सिलिंडर

आप एक ऐसा स्वतः-कॉलम क्यों चाहते हैं जो प्राथमिक कुंजी नहीं है?
दर्शन_

2
आप एक ऐसा स्वतः-कॉलम क्यों चाहते हैं जो प्राथमिक कुंजी नहीं है? संभावित कारणों में शामिल हैं: क्योंकि पीके का उपयोग पंक्तियों को शारीरिक रूप से करने के लिए भी किया जाता है। उदाहरण: मान लीजिए कि आप उपयोगकर्ताओं के लिए संदेश संग्रहीत करते हैं। आपको प्रति उपयोगकर्ता सभी संदेशों को पढ़ने की आवश्यकता है, इसलिए आप उन्हें कुशल पुनर्प्राप्ति के लिए एक साथ रखना चाहते हैं। चूंकि पीके द्वारा आप उन्हें छांटते हैं, आप ऐसा करना चाहते हैं: तालिका संदेश (उपयोगकर्ता, आईडी, txt, प्राथमिक कुंजी (उपयोगकर्ता, आईडी))
बनाएं

8

वास्तव में AUTO_INCREMENT विशेषता केवल PRIMARY KEY (किसी भी अधिक) तक सीमित नहीं है। पुराने संस्करणों में ऐसा हुआ करता था - निश्चित रूप से 3.23 और शायद 4.0। फिर भी 4.1 के बाद से सभी संस्करणों के लिए MySQL मैनुअल इस तरह से पढ़ता है

प्रति तालिका में केवल एक AUTO_INCREMENT कॉलम हो सकता है, इसे अनुक्रमित किया जाना चाहिए, और इसमें DEFAULT मान नहीं हो सकता है।

तो आप वास्तव में एक तालिका में एक AUTO_INCREMENT कॉलम रख सकते हैं जो प्राथमिक कुंजी नहीं है। अगर यह समझ में आता है, हालांकि एक अलग विषय है।

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

अंत में MySQL 4.1 और बाद में BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE के लिए एक प्रकार उर्फ सीरियल को परिभाषित करता है ।


1
+1 इस तथ्य के लिए कि auto_increment PKs तक सीमित नहीं है। सुनिश्चित नहीं हैं कि आप क्यों सोचते हैं कि सरोगेट कुंजी के लिए ऋणात्मक संख्याओं का उपयोग करने से "भारी समस्याएं" होती हैं।
nvogel

4

यह एक दिलचस्प सवाल है क्योंकि विभिन्न डेटाबेस में auto_increment प्रदान करने के लिए अद्वितीय दृष्टिकोण हैं।

MySQL : एक तालिका में एक पंक्ति को विशिष्ट रूप से पहचानने के लिए केवल एक auto_increment कुंजी उत्पन्न होती है। क्यों, लेकिन सिर्फ कार्यान्वयन के पीछे बहुत सारे स्पष्टीकरण नहीं हैं। डेटाटाइप के आधार पर, स्वत: पुनरावृत्ति मूल्य बाइट्स में डेटाटाइप की लंबाई से तय होते हैं:

  • अधिकतम टिन 127 है
  • अधिकतम अछूता टिकट 255 है
  • मैक्स INT 2147483647 है
  • मैक्स यूनिस्ड INT 4294967295 है

PostgreSQL

1 से 2,147,483,647 तक ऑटो वेतन वृद्धि के लिए आंतरिक डेटाटाइप धारावाहिक का उपयोग किया जाता है। बड़ी रेंज का उपयोग करके बड़ी रेंज की अनुमति दी जाती है।

Oracle : स्कीमा ऑब्जेक्ट जिसे SEQUENCE कहा जाता है, बस अगले फंक्शन को समन करके नए नंबर बना सकता है। PostgreSQL में भी एक ऐसा तंत्र है।

यहाँ एक अच्छा URL है जो यह बताता है कि अन्य DB उन्हें कैसे निर्दिष्ट करते हैं: http://www.w3schools.com/sql/sql_autoincrement.asp

अब आपके प्रश्न के विषय में, यदि आप वास्तव में एक ही तालिका में कई auto_increment कॉलम रखना चाहते हैं, तो आपको उसका अनुकरण करना होगा।

दो कारणों से आपको इसका अनुकरण करना चाहिए:

  1. MySQL प्रति तालिका में केवल एक वेतन वृद्धि कॉलम को समायोजित करता है जैसा कि PostgreSQL, Oracle, SQL Server और MS Access में है।
  2. MySQL में Oracle और PostgreSQL जैसी SEQUENCE स्कीमा ऑब्जेक्ट नहीं है।

आप इसका अनुकरण कैसे करेंगे ???

कई तालिकाओं का उपयोग करना, जिनमें केवल एक स्वतः सुधार कॉलम है और उन्हें लक्ष्य तालिका में इच्छित स्तंभों पर मैप करना है। यहाँ एक उदाहरण है:

इस उदाहरण को कॉपी और पेस्ट करें:

use test
DROP TABLE IF EXISTS teacher_popquizzes;
CREATE TABLE teacher_popquizzes
(
    teacher varchar(20) not null,
    class varchar(20) not null,
    pop_mon INT NOT NULL DEFAULT 0,
    pop_tue INT NOT NULL DEFAULT 0,
    pop_wed INT NOT NULL DEFAULT 0,
    pop_thu INT NOT NULL DEFAULT 0,
    pop_fri INT NOT NULL DEFAULT 0,
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
INSERT INTO teacher_popquizzes (teacher,class) VALUES
('mr jackson','literature'),
('mrs andrews','history'),
('miss carroll','spelling');
DROP TABLE IF EXISTS mon_seq;
DROP TABLE IF EXISTS tue_seq;
DROP TABLE IF EXISTS wed_seq;
DROP TABLE IF EXISTS thu_seq;
DROP TABLE IF EXISTS fri_seq;
CREATE TABLE mon_seq
(
    val INT NOT NULL DEFAULT 0,
    nextval INT NOT NULL DEFAULT 1,
    PRIMARY KEY (val)
);
CREATE TABLE tue_seq LIKE mon_seq;
CREATE TABLE wed_seq LIKE mon_seq;
CREATE TABLE thu_seq LIKE mon_seq;
CREATE TABLE fri_seq LIKE mon_seq;
BEGIN;
INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM mon_seq;
UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 2;
COMMIT;
BEGIN;
INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM tue_seq;
UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 1;
COMMIT;
BEGIN;
INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
SELECT nextval INTO @pop FROM wed_seq;
UPDATE teacher_popquizzes SET pop_wed = pop_wed + 1 WHERE id = 2;
COMMIT;
SELECT * FROM teacher_popquizzes;

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

यहाँ उदाहरण से नमूना परिणाम हैं:

mysql> CREATE TABLE teacher_popquizzes
    -> (
    ->     teacher varchar(20) not null,
    ->     class varchar(20) not null,
    ->     pop_mon INT NOT NULL DEFAULT 0,
    ->     pop_tue INT NOT NULL DEFAULT 0,
    ->     pop_wed INT NOT NULL DEFAULT 0,
    ->     pop_thu INT NOT NULL DEFAULT 0,
    ->     pop_fri INT NOT NULL DEFAULT 0,
    ->     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    -> );
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO teacher_popquizzes (teacher,class) VALUES
    -> ('mr jackson','literature'),
    -> ('mrs andrews','history'),
    -> ('miss carroll','spelling');
Query OK, 3 rows affected (0.03 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> DROP TABLE IF EXISTS mon_seq;
Query OK, 0 rows affected (0.06 sec)

mysql> DROP TABLE IF EXISTS tue_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> DROP TABLE IF EXISTS wed_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> DROP TABLE IF EXISTS thu_seq;
Query OK, 0 rows affected (0.05 sec)

mysql> DROP TABLE IF EXISTS fri_seq;
Query OK, 0 rows affected (0.07 sec)

mysql> CREATE TABLE mon_seq
    -> (
    ->     val INT NOT NULL DEFAULT 0,
    ->     nextval INT NOT NULL DEFAULT 1,
    ->     PRIMARY KEY (val)
    -> );
Query OK, 0 rows affected (0.12 sec)

mysql> CREATE TABLE tue_seq LIKE mon_seq;
Query OK, 0 rows affected (0.09 sec)

mysql> CREATE TABLE wed_seq LIKE mon_seq;
Query OK, 0 rows affected (0.08 sec)

mysql> CREATE TABLE thu_seq LIKE mon_seq;
Query OK, 0 rows affected (0.07 sec)

mysql> CREATE TABLE fri_seq LIKE mon_seq;
Query OK, 0 rows affected (0.14 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT nextval INTO @pop FROM mon_seq;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 2 rows affected (0.00 sec)

mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_tue = pop_tue + 1 WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT nextval INTO @pop FROM wed_seq;
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_wed = pop_wed + 1 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)

mysql> SELECT * FROM teacher_popquizzes;
+--------------+------------+---------+---------+---------+---------+---------+----+
| teacher      | class      | pop_mon | pop_tue | pop_wed | pop_thu | pop_fri | id |
+--------------+------------+---------+---------+---------+---------+---------+----+
| mr jackson   | literature |       0 |       1 |       0 |       0 |       0 |  1 |
| mrs andrews  | history    |       0 |       1 |       1 |       0 |       0 |  2 |
| miss carroll | spelling   |       0 |       0 |       0 |       0 |       0 |  3 |
+--------------+------------+---------+---------+---------+---------+---------+----+
3 rows in set (0.00 sec)

mysql>

यदि आपको वास्तव में MySQL में कई ऑटो वेतन वृद्धि मूल्यों की आवश्यकता है, तो यह अनुकरण करने का सबसे निकटतम तरीका है।

कोशिश करो !!!

UPDATE 2011-06-23 21:05

मैंने अभी अपने उदाहरण में देखा कि मैं @pop मान का उपयोग नहीं करता।

इस बार मैंने 'pop_tue = pop_tue + 1' को 'pop_tue = @pop' से बदल दिया और उदाहरण को वापस लिया:

mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS teacher_popquizzes;
Query OK, 0 rows affected (0.05 sec)

mysql> CREATE TABLE teacher_popquizzes
    -> (
    ->     teacher varchar(20) not null,
    ->     class varchar(20) not null,
    ->     pop_mon INT NOT NULL DEFAULT 0,
    ->     pop_tue INT NOT NULL DEFAULT 0,
    ->     pop_wed INT NOT NULL DEFAULT 0,
    ->     pop_thu INT NOT NULL DEFAULT 0,
    ->     pop_fri INT NOT NULL DEFAULT 0,
    ->     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
    -> );
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO teacher_popquizzes (teacher,class) VALUES
    -> ('mr jackson','literature'),
    -> ('mrs andrews','history'),
    -> ('miss carroll','spelling');
Query OK, 3 rows affected (0.03 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> DROP TABLE IF EXISTS mon_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> DROP TABLE IF EXISTS tue_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> DROP TABLE IF EXISTS wed_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> DROP TABLE IF EXISTS thu_seq;
Query OK, 0 rows affected (0.01 sec)

mysql> DROP TABLE IF EXISTS fri_seq;
Query OK, 0 rows affected (0.03 sec)

mysql> CREATE TABLE mon_seq
    -> (
    ->     val INT NOT NULL DEFAULT 0,
    ->     nextval INT NOT NULL DEFAULT 1,
    ->     PRIMARY KEY (val)
    -> );
Query OK, 0 rows affected (0.08 sec)

mysql> CREATE TABLE tue_seq LIKE mon_seq;
Query OK, 0 rows affected (0.09 sec)

mysql> CREATE TABLE wed_seq LIKE mon_seq;
Query OK, 0 rows affected (0.13 sec)

mysql> CREATE TABLE thu_seq LIKE mon_seq;
Query OK, 0 rows affected (0.11 sec)

mysql> CREATE TABLE fri_seq LIKE mon_seq;
Query OK, 0 rows affected (0.08 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;

Query OK, 1 row affected (0.01 sec)

mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_tue = @pop WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO tue_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;

Query OK, 2 rows affected (0.00 sec)

mysql> SELECT nextval INTO @pop FROM tue_seq;
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_tue = @pop WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.03 sec)

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO wed_seq (val) VALUES (0) ON DUPLICATE KEY UPDATE nextval = nextval + 1;

Query OK, 1 row affected (0.01 sec)

mysql> SELECT nextval INTO @pop FROM wed_seq;
Query OK, 1 row affected (0.00 sec)

mysql> UPDATE teacher_popquizzes SET pop_wed = @pop WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> COMMIT;
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT * FROM teacher_popquizzes;
+--------------+------------+---------+---------+---------+---------+---------+----+
| teacher      | class      | pop_mon | pop_tue | pop_wed | pop_thu | pop_fri | id |
+--------------+------------+---------+---------+---------+---------+---------+----+
| mr jackson   | literature |       0 |       2 |       0 |       0 |       0 |  1 |
| mrs andrews  | history    |       0 |       1 |       1 |       0 |       0 |  2 |
| miss carroll | spelling   |       0 |       0 |       0 |       0 |       0 |  3 |
+--------------+------------+---------+---------+---------+---------+---------+----+
3 rows in set (0.00 sec)

mysql>

आपका सारांश पूरी तरह से सही नहीं है: PostgreSQL किसी भी संख्या में ऑटो वेतन वृद्धि (धारावाहिक) कॉलम का समर्थन करता है, जैसे कि ओरेकल करता है (दोनों मामलों में कॉलम एक क्रम से मान से भरे हुए हैं)। PostgreSQL bigserialडेटा प्रकार भी प्रदान करता है जो एक सीमा प्रदान करता है जो 2,147,483,647 से बहुत बड़ा है
a_horse_with_no_name

@a_horse_with_no_name: निरीक्षण के लिए खेद है। मैं अभी भी एक यात्री हूं, जो पोस्टग्रैस्क्ल के साथ है। मैं बाद में अपना जवाब अपडेट करूंगा। मैं आईफोन से सड़क के जवाब पर हूं। आपका दिन शुभ हो!
रोलैंडम्यूसीडीडीबीए

0

जैसा कि XL कहता है, यह सिर्फ प्राथमिक कुंजी तक सीमित नहीं है। यह एक संभावित सीमा है कि आपके पास प्रति तालिका केवल एक ही कॉलम हो सकता है, लेकिन सबसे अच्छी बात यह है कि आपको किसी अन्य तालिका में जितने नंबर चाहिए, उतने नंबर उत्पन्न करना है और फिर उन्हें वहां डालना है जहाँ आपको ज़रूरत है।

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