Jak zrobić automatyczną inkrementację klucza podstawowego tabeli MySQL z pewnym prefiksem

80

Mam taki stół

table
id Varchar(45) NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(30) NOT NULL,

Chcę zwiększyć pole identyfikatora, np. 'LHPL001','LHPL002','LHPL003'… Itd. Co powinienem zrobić w tym celu? Proszę, daj mi znać w każdy możliwy sposób.

Vijay
źródło
po prostu dodaj kolejną kolumnę, aby to zrobić. To całkowicie normalne, że w bazie danych znajdują się „różne rodzaje” pól identyfikacyjnych.
Fattie

Odpowiedzi:

135

Jeśli naprawdę tego potrzebujesz, możesz osiągnąć swój cel za pomocą oddzielnej tabeli do sekwencjonowania (jeśli nie masz nic przeciwko) i wyzwalacza.

Tabele

CREATE TABLE table1_seq
(
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);
CREATE TABLE table1
(
  id VARCHAR(7) NOT NULL PRIMARY KEY DEFAULT '0', name VARCHAR(30)
);

Teraz spust

DELIMITER $$
CREATE TRIGGER tg_table1_insert
BEFORE INSERT ON table1
FOR EACH ROW
BEGIN
  INSERT INTO table1_seq VALUES (NULL);
  SET NEW.id = CONCAT('LHPL', LPAD(LAST_INSERT_ID(), 3, '0'));
END$$
DELIMITER ;

Następnie wystarczy wstawić wiersze do tabeli table1

INSERT INTO Table1 (name) 
VALUES ('Jhon'), ('Mark');

I będziesz mieć

| ID | NAZWA |
------------------
| LHPL001 | Jhon |
| LHPL002 | Mark |

Oto demo SQLFiddle

peterm
źródło
Czy stwierdzenie zawarte w wyzwalaczu jest atomowe? To znaczy jest możliwe, że pomiędzy INSERT i SET inny wątek / żądanie wstawia do table1_seq, powodując, że LAST_INSERT_ID () zwraca identyfikator innego żądania, a nie ten, który został wstawiony w BEGIN / END.
n00b
@peterm, mam część wyzwalacza wątpliwości. Zmieniłem SET NEW.id = CONCAT ('A', LPAD (LAST_INSERT_ID (), 4, '500')); ponieważ potrzebuję mojego identyfikatora, zaczynając od 5001, więc ustawiam 500. Więc otrzymuję wyjście A5001, które jest prawidłowe. Moja wątpliwość pojawiła się, gdy id osiągnie 5999, to jaki będzie następny identyfikator? Czy to 6000?
user9437856
Spróbowałem samemu po dodaniu rekordów do bazy danych dodałem ponad 1000 rekordów i po 5999 moja wartość id zaczyna się od V1000, co jest całkowicie błędne. Potrzebuję kontynuacji 6000,6001,6002 i tak dalej. jakiś pomysł w tym?
user9437856
18

Utwórz tabelę z normalnym numerycznym identyfikatorem auto_increment, ale zdefiniuj ją za pomocą ZEROFILLlub użyj, LPADaby dodać zera podczas wybierania. Następnie CONCATwartości, aby uzyskać zamierzone zachowanie. Przykład 1:

create table so (
 id int(3) unsigned zerofill not null auto_increment primary key,
 name varchar(30) not null
);

insert into so set name = 'John';
insert into so set name = 'Mark';

select concat('LHPL', id) as id, name from so;
+---------+------+
| id      | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+

Przykład 2:

create table so (
 id int unsigned not null auto_increment primary key,
 name varchar(30) not null
);

insert into so set name = 'John';
insert into so set name = 'Mark';

select concat('LHPL', LPAD(id, 3, 0)) as id, name from so;
+---------+------+
| id      | name |
+---------+------+
| LHPL001 | John |
| LHPL002 | Mark |
+---------+------+
Puszysty
źródło
Początkowo myślałem o zapisaniu LHPL jako oddzielnej kolumnie, a następnie konkatowaniu go przez concat (col1, col2), ale potem będzie to bolało w S, kiedy kiedyś będę musiał zmienić LHPL. Więc myślę, że zrobię to po stronie serwera programu.
4 Zostaw okładkę
3

Wiem, że jest późno, ale chcę się tylko podzielić tym, co w tym celu zrobiłem. Nie mogę dodać kolejnej tabeli ani wyzwalacza, więc po wstawieniu muszę wygenerować je w jednym zapytaniu. Czy w Twoim przypadku możesz spróbować tego zapytania.

CREATE TABLE YOURTABLE(
IDNUMBER VARCHAR(7) NOT NULL PRIMARY KEY,
ENAME VARCHAR(30) not null
);

Wykonaj selekcję i użyj tego zapytania wybierającego, a następnie zapisz parametr @IDNUMBER

(SELECT IFNULL
     (CONCAT('LHPL',LPAD(
       (SUBSTRING_INDEX
        (MAX(`IDNUMBER`), 'LHPL',-1) + 1), 5, '0')), 'LHPL001')
    AS 'IDNUMBER' FROM YOURTABLE ORDER BY `IDNUMBER` ASC)

A następnie Wstaw zapytanie będzie:

INSERT INTO YOURTABLE(IDNUMBER, ENAME) VALUES 
(@IDNUMBER, 'EMPLOYEE NAME');

Wynik będzie taki sam, jak w przypadku drugiej odpowiedzi, ale różnica polega na tym, że nie będziesz musiał tworzyć kolejnej tabeli ani wyzwalacza. Mam nadzieję, że mogę pomóc komuś, kto ma taki sam przypadek jak mój.

yhAm
źródło
0

Oto przykład PostgreSQL bez wyzwalacza, jeśli ktoś potrzebuje go na PostgreSQL:

CREATE SEQUENCE messages_seq;

 CREATE TABLE IF NOT EXISTS messages (
    id CHAR(20) NOT NULL DEFAULT ('message_' || nextval('messages_seq')),
    name CHAR(30) NOT NULL,
);

ALTER SEQUENCE messages_seq OWNED BY messages.id;
Ildar Nasurlaev
źródło