PostgreSQL: как создать последовательность с префиксом в качестве уникального идентификатора?

#sql #postgresql

#sql #postgresql

Вопрос:

Один из моих клиентов настаивает на том, чтобы я создал уникальный идентификатор, который начинается с заданного префикса, а затем увеличивается на единицу в postgres таблице. Например, PREFIX000001 .

Я знаю, что postgres предоставляет SERIAL BIGSERIAL и UUID уникальную идентификацию строк в таблице. Но клиент просто не слушает. Он хочет по-своему.

Вот пример таблицы (представление в Excel) — что-то вроде unique_id столбца, который автоматически генерируется при каждой INSERT команде: введите описание изображения здесь

Я действительно хочу знать, возможно ли это технически postgres . Как мне это сделать?

Комментарии:

1. Создайте представление, когда вам нужно отобразить измененные значения столбцов из таблицы.

2. @klin вы имеете в виду представление во внешнем интерфейсе? Да, это «обсуждалось». Бесполезно. Они хотят, чтобы это было в базе данных.

3. создать представление…

4. ооо, я обязательно займусь этим. Спасибо.

Ответ №1:

Вы могли бы создать SERIAL or BIGSERIAL , как вы предложили, но представить его строкой при сообщении данных в приложении (если клиент примет это):

  SELECT to_char(id, '"PREFIX0"FM0000000') AS unique_id, product_name, product_desc FROM table;
 

Например:

 SELECT to_char(123, '"PREFIX0"FM0000000') AS unique_id;
  unique_id  
----------------
 PREFIX00000123
(1 row)

Time: 2.704 ms
 

В противном случае вам пришлось бы сделать это:

 CREATE SEQUENCE my_prefixed_seq;

CREATE TABLE my_table (
    unique_id TEXT NOT NULL DEFAULT 'PREFIX'||to_char(nextval('my_prefixed_seq'::regclass), 'FM0000000'),
    product_name text,
    product_desc text
);

INSERT INTO my_table (product_name) VALUES ('Product 1');
INSERT INTO my_table (product_name) VALUES ('Product 2');
INSERT INTO my_table (product_name) VALUES ('Product 3');
 

->

 SELECT * FROM my_table;
   unique_id   | product_name | product_desc 
--------------- -------------- --------------
 PREFIX0000004 | Product 1    | {NULL}
 PREFIX0000005 | Product 2    | {NULL}
 PREFIX0000006 | Product 3    | {NULL}
(3 rows)

Time: 3.595 ms
 

Я бы посоветовал вам попытаться заставить клиента пересмотреть, но, похоже, вы уже пробовали этот маршрут

Для тех, кто прочитает это в будущем, пожалуйста, не делайте этого с вашей базой данных, это не очень хорошая практика, как признал @Beki в своем вопросе

Комментарии:

1. Да, объяснять своим клиентам вещи и разумно советовать им против всего, что они хотят, в Японии часто считается грубым. @Gab спасибо. Ваш ответ решает мою проблему.

Ответ №2:

Как говорит Гэб, это довольно громоздкая задача. Если вы также хотите сохранить обычный первичный ключ для внутреннего использования в вашем приложении, вот решение:

 CREATE OR REPLACE FUNCTION add_prefix(INTEGER) RETURNS text AS
$ select 'PREFIX'||to_char($1, 'FM0000000'); $
LANGUAGE sql immutable;

CREATE TABLE my_table (
    id SERIAL PRIMARY KEY,
    unique_id TEXT UNIQUE NOT NULL GENERATED ALWAYS AS 
        (add_prefix(id)) STORED,
    product_name text
);

INSERT INTO my_table (product_name) VALUES ('Product 1');
INSERT INTO my_table (product_name) VALUES ('Product 2');
INSERT INTO my_table (product_name) VALUES ('Product 3');

 select * from my_table;
 id |   unique_id   | product_name
---- --------------- --------------
  1 | PREFIX0000001 | Product 1
  2 | PREFIX0000002 | Product 2
  3 | PREFIX0000003 | Product 3
 

Конечно, вы получаете дополнительный индекс, поглощающий оперативную память и дисковое пространство впустую. Но, когда клиент затем неизбежно спрашивает вас: «Я хочу обновить уникальный идентификатор» через несколько месяцев…

Или, что еще хуже, «почему в последовательности есть дыры, вы не можете сделать так, чтобы дыр не было»…

… тогда вам не придется обновлять ВСЕ отношения во всех таблицах…

Комментарии:

1. определенно подойдет. Спасибо @bobflux

2. требуется просмотр lol youtube.com/watch?v=UMXs9i201AQ

3. довольно умный @bobflux

Ответ №3:

Один метод использует последовательность:

 create sequence t_seq;

create table t (
    unique_id varchar(255) default ('PREFIX' || lpad(nextval('t_seq')::text, 6, '0'));
)
 

Вот скрипка db<> .

Комментарии:

1. stackoverflow позволяет мне принять только один ответ. Я очень благодарен за оба ваших ответа. Если есть способ принять несколько ответов, я полностью за это. Я действительно использовал ваш ответ. Дайте мне знать, если есть какой-либо другой способ поблагодарить вас.