use AnP

if object_id(N'dbo.ips_tables_remove', N'P') is not null drop procedure dbo.ips_tables_remove
go
create procedure dbo.ips_tables_remove as begin set nocount on 
    if object_id(N'dbo._Ips', N'U') is not null drop table dbo._Ips
    if object_id(N'dbo.Ips', N'U') is not null drop table dbo.Ips
end
go

if object_id(N'dbo.ips_tables_create', N'P') is not null drop procedure dbo.ips_tables_create
go
create procedure dbo.ips_tables_create as begin set nocount on 

    if object_id(N'dbo.Ips', N'U') is null create table dbo.Ips(
        id integer not null identity(1, 1), 
        [procedure] integer not null, 
        [session] integer, 
        [address] varchar(39) not null, 
        accessible bit not null constraint df_ips_accessible default 1, 
        date_in datetime not null constraint df_ips_date_in default getdate(), 
        date_out datetime, 
        constraint pk_ips primary key clustered(id), 
        constraint fk_ips_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action,
        constraint uq_ips_address unique(address) with(fillfactor = 90), 
        constraint ck_ips_address check((
            [address] like '%._%._%._%' and 
            [address] not like '%[^0-9.]%' and 
            len([address]) - len(replace([address], '.', '')) = 3 and 
            parsename([address], 1) between 0 and 255 and 
            parsename([address], 2) between 0 and 255 and 
            parsename([address], 3) between 0 and 255 and 
            parsename([address], 4) between 0 and 255 
        ) or (
            [address] not like '%[^0-9a-fA-F:]%' and 
            [address] like '%:%' and 
            [address] not like '%:::%' and 
            [address] not like '%[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]%' and 
            len([address]) - len(replace([address], ':', '')) between 2 and 7 
        ))
    )

    if object_id(N'dbo._Ips', N'U') is null create table dbo._Ips(
        id integer not null identity(1, 1), 
        history_mode integer not null, 
        entity integer not null, 
        [procedure] integer not null, 
        [session] integer, 
        [address] varchar(39) not null, 
        accessible bit not null, 
        date_in datetime not null, 
        date_out datetime, 
        history_date datetime2 not null constraint df__ips_history_date default sysutcdatetime(), 
        constraint pk__ips primary key clustered(id), 
        constraint fk__ips_history_mode foreign key(history_mode) references dbo.HistoryModes(id) 
            on update no action 
            on delete no action,
        constraint fk__ips_procedure foreign key([procedure]) references dbo.Procedures(id) 
            on update no action 
            on delete no action
    )

end
go

execute dbo.ips_tables_create

if object_id(N'dbo.ips_tables_upgrade', N'P') is not null drop procedure dbo.ips_tables_upgrade
go
create procedure dbo.ips_tables_upgrade as begin set nocount on 

    if (select top 1 0 from information_schema.table_constraints where 
        table_catalog = db_name() and 
        table_name = 'Ips' and 
        constraint_name = 'fk_ips_session'
    ) is null alter table dbo.Ips add constraint fk_ips_session foreign key([session]) references dbo.Sessions(id) 
        on update no action 
        on delete no action
        
    if (select top 1 0 from information_schema.table_constraints where 
        table_catalog = db_name() and 
        table_name = '_Ips' and 
        constraint_name = 'fk__ips_session'
    ) is null alter table dbo._Ips add constraint fk__ips_session foreign key([session]) references dbo.Sessions(id) 
        on update no action 
        on delete no action

end
go

if object_id(N'dbo.ips_trigger', N'TR') is not null drop trigger dbo.ips_trigger
go
create trigger dbo.ips_trigger on dbo.Ips for insert, update, delete as begin set nocount on 

    declare @insert integer, @update integer, @delete integer, @unknown integer

    execute dbo.history_mode_get @insert output, @update output, @delete output, @unknown output

    -- update.
    insert into dbo._Ips(history_mode, entity, [procedure], [session], [address], accessible, date_in, date_out) 
    select @update, inserted.id, inserted.[procedure], inserted.[session], inserted.[address], inserted.accessible, inserted.date_in, inserted.date_out 
    from inserted inserted 
    join deleted deleted on inserted.id = deleted.id 
    where 
        inserted.[procedure] != deleted.[procedure] or 
        inserted.[session] != deleted.[session] or 
        inserted.[address] != deleted.[address] or 
        inserted.accessible != deleted.accessible or 
        inserted.date_in != deleted.date_in or 
        isnull(inserted.date_out, '0001-01-01') != isnull(deleted.date_out, '0001-01-01')

    -- Insert.
    insert into dbo._Ips(history_mode, entity, [procedure], [session], [address], accessible, date_in, date_out) 
    select @insert, inserted.id, inserted.[procedure], inserted.[session], inserted.[address], inserted.accessible, inserted.date_in, inserted.date_out 
    from inserted inserted 
    left join deleted deleted on inserted.id = deleted.id 
    where deleted.id is null

    -- deleted.
    insert into dbo._Ips(history_mode, entity, [procedure], [session], [address], accessible, date_in, date_out) 
    select @delete, deleted.id, deleted.[procedure], deleted.[session], deleted.[address], deleted.accessible, deleted.date_in, deleted.date_out 
    from deleted deleted 
    left join inserted inserted on deleted.id = inserted.id 
    where inserted.id is null

end
go