Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Покритикуйте решение...  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 659
Есть сервер 2000, переходим на 2008R2.
Система работает по записям. На встаставку кажтой записи используется всвоя процедудура -> купсоры :-(((
Есть одна ососбенность - сквозные идентификаторы по всей БД
+ Как есть сейчас

create procedure dbo.ap_getid @id numeric out
as
declare @site_id numeric(2,0),
        @user_id numeric
begin
   select @site_id=id from t_sites where is_local=1
   if @@error!=0 return
   if @site_id is null begin
      raiserror 40000 'Неизвестна площадка'
      return
   end
   insert t_idgenerator (site_id) values (@site_id)
   if @@error!=0 return
   select @id = @@identity + @site_id*10000000000000000
end

+ Хочу сделать так

IF OBJECT_ID(N'[dbo].[t_idgenerator]', N'U') IS NULL
BEGIN
    CREATE TABLE [dbo].[t_idgenerator](
        [id]      [numeric](16, 0) IDENTITY(1,1) NOT NULL
      , [site_id] [numeric](2, 0)  NOT NULL
      , [f_id]    [numeric](18, 0) NULL
    ) ON [PRIMARY]
END
GO
IF OBJECT_ID(N'[dbo].[t_table]', N'U') IS NULL
BEGIN
    CREATE TABLE [dbo].[t_table](
        [id]        [numeric](16, 0) IDENTITY(1,1) NOT NULL
      , [item_name] [varchar](255)
    ) ON [PRIMARY]
END
GO
IF EXISTS(SELECT 1
              FROM [sys].[types] t
              WHERE 1 = 1
                AND t.[name]  = N'TVP_t_table'
                AND t.[schema_id] = SCHEMA_ID('dbo')
                AND t.[is_table_type] = 1)
    DROP TYPE [dbo].[TVP_t_table]
GO
CREATE TYPE [dbo].[TVP_t_table] AS TABLE(
    [id]         [numeric](18, 0)
  , [f_id]       [numeric](18, 0) IDENTITY(1,1)
  , [item_name]  [varchar](255)
)
GO
IF EXISTS(SELECT 1
              FROM [sys].[types] t
              WHERE 1 = 1
                AND t.[name]  = N'TVP_id_gen'
                AND t.[schema_id] = SCHEMA_ID('dbo')
                AND t.[is_table_type] = 1)
    DROP TYPE [dbo].[TVP_id_gen]
GO
CREATE TYPE [dbo].[TVP_id_gen] AS TABLE(
    [id]         [numeric](18, 0)
  , [f_id]       [numeric](18, 0)
)
GO

DECLARE @t [dbo].[TVP_t_table]
      , @id [dbo].[TVP_id_gen]
      , @site_id [numeric](2, 0)

SELECT @site_id = [s].[id] FROM [dbo].[t_sites] [s] WHERE [s].[is_local] = 1

INSERT INTO @t([item_name])
SELECT TOP 3 [t].[TABLE_NAME]
    FROM INFORMATION_SCHEMA.TABLES [t]

----- Собственно получение новых идентификаторов
INSERT INTO [dbo].[t_idgenerator]([site_id], [f_id])
    OUTPUT INSERTED.site_id * 10000000000000000 + INSERTED.id, INSERTED.[f_id]
    INTO @id
SELECT @site_id, [t].[f_id]
    FROM @t [t]

----- Обновление табличной переменной
UPDATE [t]
    SET [id] = [id].[id]
    FROM @t [t]
         INNER JOIN @id [id] ON [id].[f_id] = [t].[f_id]

----- Вставка записей в постоянную таблицу
INSERT INTO [dbo].[t_table]([id], [item_name])
SELECT [t].[id], [t].[item_name] FROM @t [t]

Погонял сие творение несколько раз из разных сессий с разной временной задержкой дубликатов не было.
Есть ли что-нибудь, что я не учел?
6 июн 11, 06:49    [10766954]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте решение...  [new]
aleks2
Guest
Оба решения маразм в чистом и незамутненном виде.

1. Не экономьте поля в таблицах.
2. Идентити или guid - это единственно правильный подход.
3. Составные идентификаторы ничем не хуже одиночных.
2. Если очень нада АДЫН идентификатор - ваяйте вычисляемый столбец.
6 июн 11, 07:19    [10766978]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте решение...  [new]
Guf
Member

Откуда: Новосибирск
Сообщений: 659
aleks2
Оба решения маразм в чистом и незамутненном виде.

Согласен полностью, но я исхожу из того, что есть. Система древняя, разрабатывалась как коробочный продукт с одним интерфейсом, под две СУБД (MS SQL Server и Sybase). Наша компания его давно купила и успешно работает. Мы с самого начала использовали скуль. Сейчас купили новый сервер и переносим БД на 2008 R2.
+ Разработчики заложили такой принцип:

----- Главная таблица, в которой хранятся все объекты их типы, состояния и имена.
CREATE TABLE [dbo].[t_items](
	[id] [numeric](18, 0) NOT NULL,
	[type_id] [numeric](18, 0) NOT NULL, -- справочник типов объектов
	[item_name] [varchar](255) NOT NULL DEFAULT (''),
	[state_id] [numeric](18, 0) NOT NULL, -- справочник состояний объектов
	[item_remark] [varchar](255) NULL
)
У всех других таблиц есть поле id и они связаны с t_items по этому полю (один к одному)
В БД нет, совсем нет, ни констрейнтов, ни внешних ключей, ни тригеров, ни функций. Есть только индексы кластерные/некластерные и процедуры.

Сквозная нумерация да еще и с префиксами, видимо, была задумана разработчиками для репликации, которая к счастью ;-) так и не была реализована. Для меня доступна лишь часть исходного кода. И пока мне приходится мириться именно с таким положением дел.
По-этому я и ищу варианты для улучшения системы В частности, сейчас вопрос стоит в избавлении системы от туевой хучи не нужных курсоров и позаписной обработки.

aleks2
1. Не экономьте поля в таблицах.

1. И не собираюсь.
aleks2
2. Идентити или guid - это единственно правильный подход.

2. Как раз сейчас почти так, и реализовано - в таблице t_idgenerator поле [id] [numeric](16, 0) IDENTITY(1,1) NOT NULL
aleks2
3. Составные идентификаторы ничем не хуже одиночных.

3. Согласен. Но пока в каждой таблице должно быть поле id, и обязана существовать запись с такимже id в таблице t_items.
aleks2
4. Если очень нада АДЫН идентификатор - ваяйте вычисляемый столбец.

4. Готов взять на вооружение, только пока не улавливаю идею. Можно изложить основные моменты?
6 июн 11, 11:44    [10768432]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить