Последовательность в postgresql - PullRequest
0 голосов
/ 31 августа 2018

Преобразование ниже процедур и таблиц SQL Server для хранения и генерации последовательности в postgresql.

Кто-нибудь может подсказать, как это сделать в Postgres (через таблицу и эту функцию), а не через последовательность или nextval или currval

Таблица последовательности

IF NOT EXISTS (SELECT name FROM sys.tables WHERE name = 'testtable')                                
    CREATE TABLE dbo.testtable(Sequence int NOT NULL )                              
go                              
IF NOT EXISTS (SELECT * FROM testtable)                             
    INSERT INTO testtable VALUES (-2147483648)                              
go          

Процесс создания последовательности

CREATE PROCEDURE test_proc                                              
AS                                              
SET NOCOUNT ON                                              
DECLARE @iReturn int                                                
BEGIN TRANSACTION                                               
    SELECT @iReturn = Sequence FROM schema.test (TABLOCKX) -- set exclusive table lock                                          
    UPDATE schema.test SET Sequence = ( Sequence + 1 )                                          
COMMIT TRANSACTION                                              
SELECT @iReturn                                             
RETURN @iReturn                                                 
go                                              
grant execute on schema.test to public                                              
go                                      

1 Ответ

0 голосов
/ 31 августа 2018

Отказ от ответственности: использование последовательности является единственным масштабируемым и эффективным способом создания уникальных чисел.


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

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

create table seq_generator
(
   entity     varchar(30)            not null primary key,
   seq_value  integer      default 0 not null 
);

insert into seq_generator (entity) values ('testsequence');

Затем создайте функцию для увеличения значения последовательности:

create or replace function next_value(p_entity varchar)
  returns integer
as
$$
  update seq_generator 
     set seq_value = seq_value + 1
  where entity = lower(p_entity)
  returning seq_value;
$$
language sql;

Для получения следующего значения последовательности, например, внутри вставки:

insert into some_table 
  (id, ...)
values 
  (next_value('testsequence'), ...);

Или сделать его значением по умолчанию:

create table some_table
(
  id integer not null primary key default next_value('testsequence'),
  ...
);

UPDATE увеличивает и блокирует строку в одном операторе, возвращая новое значение для последовательности. Если вызывающая транзакция фиксируется, обновление до seq_generator также будет зафиксировано. Если вызывающая транзакция откатывается, обновление также откатывается.

Если вторая транзакция вызывает next_value() для того же объекта, она должна ждать, пока первая транзакция не завершится или не откатится.

Таким образом, доступ к генератору сериализуется через эту функцию. Только одна транзакция за раз может сделать это.

Если вам нужна вторая последовательность без пропусков, просто вставьте новую строку в таблицу `seq_generator '.


Это серьезно повлияет на производительность при использовании в среде, которая выполняет много одновременных вставок.

Причина only , которая могла бы оправдать это, является юридическим требованием иметь номер без пробелов. В любом другом случае вы должны действительно использовать последовательность Postgres.

...