MySQL이 auto_increment 열을 기본 키로 제한한다는 것을 알고 있습니다. 왜 이런거야? 필자의 첫 번째 생각은 성능 제한이라는 것입니다.이 값을 얻기 위해 잠겨 야 할 카운터 테이블이있을 수 있기 때문입니다.
같은 테이블에 여러 auto_increment 열을 가질 수없는 이유는 무엇입니까?
감사.
MySQL이 auto_increment 열을 기본 키로 제한한다는 것을 알고 있습니다. 왜 이런거야? 필자의 첫 번째 생각은 성능 제한이라는 것입니다.이 값을 얻기 위해 잠겨 야 할 카운터 테이블이있을 수 있기 때문입니다.
같은 테이블에 여러 auto_increment 열을 가질 수없는 이유는 무엇입니까?
감사.
답변:
기본 키가 아닌 auto_increment 열을 원하는 이유는 무엇입니까?
정의에 따라 열을 자동 증분으로 만들려면 해당 열에 의미있는 데이터를 저장하지 않습니다. 의미없는 정보를 저장하는 것이 합리적 일 경우는 합성 기본 키를 가지려는 특별한 경우입니다. 이 경우 정보의 부족은 누군가가 미래에 와서 일부 개체의 일부 속성이 변경되어 데이터를 변경하려는 위험이 없기 때문에 이점이 있습니다.
동일한 테이블에 여러 auto_increment 열이 있으면 더 이상하게 보입니다. 두 열의 데이터는 동일합니다. 동일한 알고리즘에 의해 생성되고 결국에는 동시에 채워집니다. 동시 세션이 충분하면 동기화가 약간 벗어날 수있는 구현을 생각해 낼 수 있다고 가정합니다. 그러나 그것이 응용 프로그램에서 어떻게 유용할지 상상할 수 없습니다.
실제로 AUTO_INCREMENT 속성은 PRIMARY KEY (더 이상)로 제한되지 않습니다. 예전 버전에서는 -3.23, 아마도 4.0이었습니다. 4.1 이후 모든 버전에 대한 MySQL 매뉴얼 은 여전히 다음과 같습니다.
테이블 당 하나의 AUTO_INCREMENT 열만있을 수 있으며 인덱스되어야하며 DEFAULT 값을 가질 수 없습니다.
따라서 기본 키가 아닌 테이블에 AUTO_INCREMENT 열을 실제로 가질 수 있습니다. 이해가 되더라도 다른 주제입니다.
또한 AUTO_INCREMENT 열은 항상 정수 유형이어야하며 (기술적으로 부동 소수점 유형도 허용됨) UNSIGNED 여야합니다. SIGNED 형식은 키 공간의 절반을 낭비 할뿐만 아니라 실수로 음수 값을 삽입하면 큰 문제가 발생할 수 있습니다.
마지막으로 MySQL 4.1 이상 은 BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE에 대한 타입 별칭 SERIAL 을 정의합니다 .
다른 데이터베이스에는 auto_increment를 제공하기위한 고유 한 접근 방식이 있기 때문에 이것은 흥미로운 질문입니다.
MySQL : 하나의 auto_increment 키만 생성되어 테이블에서 행을 고유하게 식별합니다. 이유 뒤에는 설명이 많지 않지만 구현 만 있습니다. 데이터 유형에 따라 auto_increment 값은 데이터 유형의 길이 (바이트)로 고정됩니다.
내부 데이터 유형 시리얼은 1에서 2,147,483,647로 자동 증분하는 데 사용됩니다. 더 큰 범위는 더 큰 직렬을 사용하여 허용됩니다.
Oracle : SEQUENCE라는 스키마 객체는 단순히 nextval 함수를 소환하여 새로운 숫자를 생성 할 수 있습니다. PostgreSQL에는 이러한 메커니즘이 있습니다.
다음은 다른 DB가 지정하는 방법을 제공하는 멋진 URL입니다. http://www.w3schools.com/sql/sql_autoincrement.asp
이제 귀하의 질문에 대해, 단일 테이블에 여러 auto_increment 열을 실제로 갖고 싶다면 그것을 모방해야합니다.
이것을 에뮬레이션해야하는 두 가지 이유 :
그것을 어떻게 모방하겠습니까? ???
auto_increment 열이 하나만있는 여러 테이블을 사용하고 대상 테이블의 원하는 열에 매핑합니다. 예를 들면 다음과 같습니다.
이 예제를 복사하여 붙여 넣기 :
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;
교사를위한 팝 퀴즈 테이블이 생성됩니다. 또한 한 주에 하나씩 5 개의 시퀀스 에뮬레이터를 만들었습니다. 각 시퀀스 에뮬레이터는 val 열에 값 0을 삽입하여 작동합니다. 시퀀스 에뮬레이터가 비어 있으면 val 0, nextval 1로 시작합니다. 그렇지 않으면 nextval 열이 증가합니다. 그런 다음 시퀀스 에뮬레이터에서 nextval 열을 가져올 수 있습니다.
예제의 샘플 결과는 다음과 같습니다.
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에서 여러 개의 자동 증분 값이 실제로 필요한 경우이를 가장 유사한 방법으로 에뮬레이션 할 수 있습니다.
시도 해봐 !!!
업데이트 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>
bigserial
2,147,483,647보다 훨씬 큰 범위를 제공하는 데이터 유형을 제공합니다