Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Последовательная нумерация в пределах группы записей / 14 сообщений из 14, страница 1 из 1
22.05.2016, 07:43
    #39240835
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
У меня есть таблица примерно вот такого вида:

Код: plaintext
1.
2.
3.
Организация  Подразделение  Отдел  Группа        Номер          .....
-----------  -------------  -----  ------    -------------     -------
     01            01         01      01     01_01_01_01_1


Поле Номер должно быть уникально и заполняться автоматически (требования бизнеса).

Алгоритм заполнения: Организация + Подразделение + Отдел + Группа + [Очередной порядковый номер в пределах четырех предыдущих полей].

Табличка будет большая - основная таблица в БД, миллионы записей.

Пользователей много, 99% из них работают с этой таблицей. 80% чтений.

Как лучше решить такую задачу?

Делать

Код: plaintext
1.
SELECT MAX(...) FROM TABLE WHERE [Организация] = ... AND [Подразделение] = ... AND [Отдел] = .... AND [Группа] = ....

даже при наличии индексов по этим полям мне кажется не очень удачной идеей.

Autoincremented поля и SEQUENCE здесь не подходят в силу того, что нумерация не сквозная, а рамках группы записей.

Пока думаю над вариантом создания еще одной таблицы, в которой будет храниться следующей номер, который должен быть выделен в пределах выбранной группы полей:

Код: plaintext
1.
2.
3.
Организация  Подразделение  Отдел  Группа   Следующий номер        
-----------  -------------  -----  ------    -------------     
     01            01         01      01           1

Соответвенно при вставке записи в основную таблицу в триггере получать значение [Следующий номер], использовать его в основной таблице, а потом увеличивать значение в вспомогательной таблице.

Может есть решения лучше ?
...
Рейтинг: 0 / 0
22.05.2016, 07:47
    #39240836
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
Да, забыл добавить - сгенерированный номер не должен меняться для записи. Это номер, который пойдет в бумажные документы и по нему потом будет искаться запись.
...
Рейтинг: 0 / 0
22.05.2016, 11:16
    #39240854
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
expl0rerМожет есть решения лучше ?Посмотрите Организация пользовательских счетчиков (генераторов) в Microsoft SQL Server , оно уже стало классикой :-)
...
Рейтинг: 0 / 0
22.05.2016, 12:07
    #39240864
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
Да, спасибо - похоже то, что нужно. Я правильно понял, что на основную таблицу мне нужно повесить триггер на вставку. В этом триггере я буду проверять если у меня уже в таблице счетчиков счетчик с нужной комбинацией ключевых полей. Если нет - создавать его. А триггер повешенный на таблицу счетчиков будет создавать SEQUENCE и функции для работы с ней?
...
Рейтинг: 0 / 0
22.05.2016, 12:35
    #39240870
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
alexeyvgоно уже стало классикой :-)Классика - когда не нужна транзакционность при генерации.
ТС'у же наоборот, транзакционность генерации нужна.

expl0rer
Код: plaintext
1.
SELECT MAX(...) FROM TABLE WHERE [Организация] = ... AND [Подразделение] = ... AND [Отдел] = .... AND [Группа] = ....
даже при наличии индексов по этим полям мне кажется не очень удачной идеей.Нормальная идея. И индекс нужен один: (Организация, Подразделение, Отдел, Группа, Номер).
Запрос должен выглядеть так:
Код: sql
1.
SELECT @ПоследнийНомер = MAX(...) FROM TABLE with (serializable, updlock) WHERE [Организация] = ... AND [Подразделение] = ... AND [Отдел] = .... AND [Группа] = ....

и быть в одной транзакции со вставкой в таблицу.

Если потребуется одновременная генерации по нескольким сочетаниям (Организация, Подразделение, Отдел, Группа), запрос и индекс придется доработать.
...
Рейтинг: 0 / 0
22.05.2016, 12:56
    #39240874
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
invmКлассика - когда не нужна транзакционность при генерации.

А в чем именно нарушается транзакционность в предложенном решении? Точнее, какие именно следствия в моему случае вследствие нарушения транзакционности?
...
Рейтинг: 0 / 0
22.05.2016, 14:31
    #39240894
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
expl0rerТочнее, какие именно следствия в моему случае вследствие нарушения транзакционности?К нарушению непрерывности номеров.

Это лечится отключением "автономности" генерации в этом решении. Но даже если так сделать - это не особо поможет.
Вам, по сути, требуется множество генераторов на одну таблицу. А такого там не предусмотрено. Следовательно, придется дорабатывать под свои нужды.

Как по мне, для вашего конкретного случая гораздо проще и эффективнее сделать примерно так:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
use tempdb;
go

create table dbo.t (id int identity primary key, a int, b int, c int, n int, s varchar(100));
create index IX_t__a__b__c__n on dbo.t (a, b, c, n desc)
go

create trigger dbo.tr_t__iofinsert
on dbo.t
instead of insert
as
begin
 set nocount on;

 declare @g table (a int, b int, c int, base int, primary key (a, b, c));

 with s as
 (
  select top (1) with ties
   t.a, t.b, t.c, t.n
  from
   (select distinct a, b, c from inserted) i join
   dbo.t t with (index = IX_t__a__b__c__n, serializable, updlock) on t.a = i.a and t.b = i.b and t.c = i.c
  order by
   t.n desc
 )
 insert into dbo.t
  (a, b, c, n, s)
  select
   i.a, i.b, i.c, isnull(s.n, 0) + row_number() over (partition by i.a, i.b, i.c order by (select 1)), i.s
  from
   inserted i left join
   s on s.a = i.a and s.b = i.b and s.c = i.c
end;
go

insert into dbo.t
values
 (1, 1, 1, null, 'a'), (1, 1, 1, null, 'b'),
 (1, 1, 2, null, 'c'), (1, 1, 2, null, 'd')

select * from dbo.t order by a, b, c, n;
go

insert into dbo.t
values
 (1, 1, 1, null, 'e'), (1, 1, 1, null, 'f'),
 (1, 1, 2, null, 'g'), (1, 1, 2, null, 'h')

select * from dbo.t order by a, b, c, n;
go

drop table dbo.t;
go

...
Рейтинг: 0 / 0
22.05.2016, 18:49
    #39240954
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
invmТС'у же наоборот, транзакционность генерации нужна.Ну, вообще он про это не писал.

Если транзакционность нужна, что можно использовать ту схему, про которую ТС писал, в чём проблема?

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

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

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

Дмитрий Костылев в докладах иллюстрировал этот код как раз такими сложными случаями, как у ТС, типа отдельная нумерация для периодов, для подразделений, для "групп по 1000", для клиентов, и прочими причудливыми потребностями бизнес-пользователей.
...
Рейтинг: 0 / 0
22.05.2016, 20:03
    #39240976
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
alexeyvgНу, вообще он про это не писал."Очередной порядковый номер в пределах четырех предыдущих полей" как бы намекает на непрерывность. По крайней мере, я понял именно так.

alexeyvgТам просто пример реализации автономной транзакции.

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

Дмитрий Костылев в докладах иллюстрировал этот код как раз такими сложными случаями, как у ТС, типа отдельная нумерация для периодов, для подразделений, для "групп по 1000", для клиентов, и прочими причудливыми потребностями бизнес-пользователей.Вот именно. Принцип один - либо доп. таблица, либо на основе основной.
А весь огород с CLR необходим если нужны "автономные" транзакции или возможность получать номера функцией.
...
Рейтинг: 0 / 0
22.05.2016, 20:39
    #39240989
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
Прошу прощения, что сразу не написал. В таком виде транзакционность мне не нужна - пропуски могут быть, главное чтобы их было не очень много. Автоинкрементируемое поле не устраивает клиента своим размером - им нужен короткий 3-4 символьный номер. Если нумеровать в пределах Организация+Подразделение+Отдел+Группа - так и выходит.

А если некоторые номера будут пропущены, не страшно.
...
Рейтинг: 0 / 0
22.05.2016, 20:54
    #39240991
invm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
expl0rer,

Варианты вам были предложены. Даже с примером.
Но выбрать вы должны самостоятельно.
...
Рейтинг: 0 / 0
22.05.2016, 20:59
    #39240993
expl0rer
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
да, спасибо
...
Рейтинг: 0 / 0
23.05.2016, 10:25
    #39241201
alexeyvg
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
expl0rerВ таком виде транзакционность мне не нужна - пропуски могут быть, главное чтобы их было не очень многоНу, тогда выбор простой - по любому своя таблица (таблицы) с номерами, и дальше либо простые запросы для получения номера, если производительность некритична, либо отдельные транзакции через CLR как в статье выше, если множество конкурентных обращений.

PS ждём реализации в MSSQL нативных автономных транзакций :-)
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
24.04.2018, 14:04
    #39635411
Cristiano_Rivaldo
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Последовательная нумерация в пределах группы записей
Всем привет.Ничего нового по этой теме не появилось ?
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Последовательная нумерация в пределах группы записей / 14 сообщений из 14, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]