Audit history of sql child table - sql

I'm recording all insert and update on TaskDetail table using a trigger,Now I want to assign multiple staff to a task, But if staff id stored in different child table how can I track audit history, I have considered storing staff id as comma separated values but child table is always a good option.
In TaskStaff table multiple staff will have same taskId
CREATE TRIGGER [dbo].[TaskDetail_History_Trigger]
ON [dbo].[TaskDetail]
FOR Insert,UPDATE
AS
INSERT INTO TaskHistory SELECT * FROM inserted
GO
ALTER TABLE [dbo].[ProductionDetail] ENABLE TRIGGER [Task_History_Trigger]
GO
CREATE TABLE [dbo].[TaskDetail](
[Id] [int] IDENTITY(1,1) NOT NULL,
[StaffId] [int] NULL,
CONSTRAINT [PK_ProductionDetail_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[TaskHistory](
[HistoryId] [int] IDENTITY(1,1) NOT NULL,
[Id] [int] NOT NULL,
[StaffId] [int] NULL,
CONSTRAINT [PK_ProductionDetail_1] PRIMARY KEY CLUSTERED
(
[Id] ASC
)
CREATE TABLE [dbo].[TaskStaff](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TaskId] [int] NOT NULL,
[StaffId] [int] NOT NULL,
CONSTRAINT [PK_ProductionDetailStaff] PRIMARY KEY CLUSTERED
(
[Id] ASC
)

Related

T-SQL split table vertically (moving column) with (almost) same performance

In T-SQL (MS SQL Server 2016) I want to split vertically a big table (220 GB - 500 million rows) as some columns data are descriptions and some are daily data.
So from
CREATE TABLE [BigTable](
[OptionID] [int] NOT NULL,
[Date] [datetime] NOT NULL,
[ParentID] [bigint] NOT NULL,
[Description] [char](255) NOT NULL,
[Price] [real] NULL,
[PriceTheo] [real] NULL
CONSTRAINT [PK_BigTable] PRIMARY KEY CLUSTERED
(
[ParentID] ASC,
[Date] ASC,
[OptionID] ASC
) ON [PRIMARY]
) ON [PRIMARY]
GO
I would move to:
CREATE TABLE [DescriptionTable](
[OptionVersionID] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,
[OptionID] [int] NOT NULL,
[ParentID] [bigint] NOT NULL,
[Description] [char](255) NOT NULL,
CONSTRAINT [PK_DescriptionTable] PRIMARY KEY CLUSTERED
([OptionVersionID] ASC) ON [PRIMARY]) ON [PRIMARY]
CREATE TABLE [DailyTable](
[OptionVersionID] [int] NOT NULL,
[Date] [datetime] NOT NULL,
[Price] [real] NULL,
[PriceTheo] [real] NULL
CONSTRAINT [PK_DailyTable] PRIMARY KEY CLUSTERED
([OptionVersionID] ASC,[Date] ASC) ON [PRIMARY]) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_DailyTable_Date] ON [DailyTable]
([Date] ASC) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_DailyTable_OptionVersionID] ON [DailyTable]
([OptionVersionID] ASC) ON [PRIMARY]
GO
ALTER TABLE [DailyTable] WITH CHECK ADD CONSTRAINT [FK_DailyTable_DescriptionTable] FOREIGN KEY([OptionVersionID])
REFERENCES [DescriptionTable] ([OptionVersionID])
GO
ALTER TABLE [DailyTable] CHECK CONSTRAINT [FK_DailyTable_DescriptionTable]
GO
I then create a view
CREATE VIEW [vBigTable]
AS
SELECT
[OptionID],
[Date],
[ParentID],
[Description],
[Price],
[PriceTheo]
FROM DailyTable da INNER JOIN
DescriptionTable de ON da.OptionVersionID = de.OptionVersionID
I thought I should get the same kind of performance (almost) when I request data from the view vBigTable but actually I don't (some request can be 10x slower). Do I miss something to have almost the same performance when I select, join, group by ... (only reading data) from vBigTable or even when I use the specific INNER JOIN between Description and Daily table?
PS: I have more non clustered indices and columns in real life.

Get all users how have multiple roles of certain type of roles

I have a user_roles table in which the user can have more than one active role from one type (RoleID) but in more than one region (RegionID) as in the sql table code, i want to get all the users who have more than one active role in more than one type.
table creation code:
CREATE TABLE [dbo].[UserRole](
[ID] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[UserID] [int] NOT NULL,
[RoleID] [int] NOT NULL,
[RegionID] [int] NULL,
[IsActive] [bit] NOT NULL )

SQL foreign key constraint with additional column value check

I have this situation
CREATE TABLE [dbo].[Customer]
(
Id INT IDENTITY(1,1) NOT NULL,
IsWholesaler BIT NOT NULL,
Name NVARCHAR(255) NOT NULL
)
CREATE TABLE [dbo].[WholesalerUser]
(
Id INT IDENTITY(1,1) NOT NULL,
CustomerId INT NOT NULL,
UserId INT NOT NULL
)
CREATE TABLE [dbo].[User]
(
Id INT IDENTITY(1,1) NOT NULL,
Name NVARCHAR(255)
)
One Customer which has IsWholesaler column set to true can have multiple users.
I have WholesalerUser table for this purpose but the Foreign key WholesalerUser.CustomerId is attached to Customer.Id but how to check the column IsWholesaler = 1 ?
Foreign key can be defined over several columns at once.
Add a column IsWholesaler to the WholesalerUser.
Add a check constraint to make sure that it is always 1.
Define foreign key over two columns (CustomerId, IsWholesaler).
To define such foreign key the Customer table should have either primary key as (ID, IsWholesaler), or a separate unique index on (ID, IsWholesaler).
Table Customer
CREATE TABLE [dbo].[Customer](
[Id] [int] IDENTITY(1,1) NOT NULL,
[IsWholesaler] [bit] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
CONSTRAINT [PK_Customer] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
Unique index to support foreign key constraint:
CREATE UNIQUE NONCLUSTERED INDEX [IX_ID_IsWholesaler] ON [dbo].[Customer]
(
[Id] ASC,
[IsWholesaler] ASC
)
Table WholesalerUser
CREATE TABLE [dbo].[WholesalerUser](
[Id] [int] IDENTITY(1,1) NOT NULL,
[CustomerId] [int] NOT NULL,
[IsWholesaler] [bit] NOT NULL,
[UserId] [int] NOT NULL,
CONSTRAINT [PK_WholesalerUser] PRIMARY KEY CLUSTERED
(
[Id] ASC
))
Foreign key
ALTER TABLE [dbo].[WholesalerUser] WITH CHECK
ADD CONSTRAINT [FK_WholesalerUser_Customer]
FOREIGN KEY([CustomerId], [IsWholesaler])
REFERENCES [dbo].[Customer] ([Id], [IsWholesaler])
GO
ALTER TABLE [dbo].[WholesalerUser]
CHECK CONSTRAINT [FK_WholesalerUser_Customer]
GO
Check constraint
ALTER TABLE [dbo].[WholesalerUser] WITH CHECK
ADD CONSTRAINT [CK_WholesalerUser]
CHECK (([IsWholesaler]=(1)))
GO
ALTER TABLE [dbo].[WholesalerUser]
CHECK CONSTRAINT [CK_WholesalerUser]
GO
ALTER TABLE [dbo].[WholesalerUser]
ADD CONSTRAINT [DF_WholesalerUser_IsWholesaler]
DEFAULT ((1)) FOR [IsWholesaler]
GO

SQL Azure unique nonclustered constraint

Does SQL Azure support unique non-clustered constraints? Something like that:
CREATE TABLE [dbo].[MyTable] (
[Id] [int] IDENTITY(1,1) NOT NULL,
[FieldA] [nvarchar](50) NULL,
[FieldB] [nvarchar](50) NULL,
[FieldC] [int] NULL,
CONSTRAINT [PK_Id] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [UQ_ABC] UNIQUE NONCLUSTERED ([FieldA], [FieldB], [FieldC])
It is supported, between ending ) is missing in the above statement if that is troubling you

Inserting into many-to-many table in SQL Server

This is my Tag table:
CREATE TABLE [dbo].[Tag](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](max) NULL,
[CreationDate] [datetime] NOT NULL,
[TagSlug] [nvarchar](max) NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
and this is my Post table:
CREATE TABLE [dbo].[Post](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Title] [nvarchar](400) NOT NULL,
[Body] [nvarchar](max) NOT NULL,
[Summary] [nvarchar](max) NOT NULL,
[CreationDate] [datetime] NOT NULL,
[UrlSlug] [nvarchar](max) NOT NULL,
[Picture] [nvarchar](max) NULL,
[TagId] [int] NOT NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [dbo].[Post] WITH CHECK ADD CONSTRAINT [Post_Tag] FOREIGN KEY([TagId])
REFERENCES [dbo].[Tag] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post] CHECK CONSTRAINT [Post_Tag]
GO
I just wanna to insert the Id from Tag and PostId from Post into a new table named Post_Tag which is a many to many relation, this is the script of my Post_Tag table:
CREATE TABLE [dbo].[Post_Tag](
[PostId] [int] NOT NULL,
[TagId] [int] NOT NULL,
CONSTRAINT [PK_dbo.Post_Tag] PRIMARY KEY CLUSTERED ([PostId] ASC, [TagId] ASC)
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Post_Tag] WITH CHECK
ADD CONSTRAINT [FK_dbo.Post_Tag_dbo.Post_PostId]
FOREIGN KEY([PostId]) REFERENCES [dbo].[Post] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post_Tag] CHECK CONSTRAINT [FK_dbo.Post_Tag_dbo.Post_PostId]
GO
ALTER TABLE [dbo].[Post_Tag] WITH CHECK
ADD CONSTRAINT [FK_dbo.Post_Tag_dbo.Tag_TagId]
FOREIGN KEY([TagId]) REFERENCES [dbo].[Tag] ([Id])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[Post_Tag] CHECK CONSTRAINT [FK_dbo.Post_Tag_dbo.Tag_TagId]
GO
Now, to do that I've tried the below query:
insert into [Blog].[dbo].[Post_Tag] (PostId,TagId)
select [Id] as [PostId] from [OldBlog].[dbo].[Tag]
select [TagId] from [OldBlog].[dbo].[Post]
but this error appear while running the script:
The select list for the INSERT statement contains fewer items than the insert list. The number of SELECT values must match the number of INSERT columns.
what's wrong with my query? thanks
The 2 select queries are being processed separately. You will have to come up with a way to join [OldBlog].[dbo].[Tag] to [OldBlog].[dbo].[Post] so you can insert fields PostId,TagId into [Blog].[dbo].[Post_Tag] from this new table expression.
For this, you can use the row number of each row from the two select statements as a link so you can join them and select what you need from both of them.
SELECT POST.[PostId], TAG.[TagId]
FROM (
select ROW_NUMBER() OVER (ORDER BY [Id]) AS Link, [Id] as [PostId] from [OldBlog].[dbo].[Tag]) AS POST
JOIN (
select ROW_NUMBER() OVER (ORDER BY [TagId]) AS Link, [TagId] from [OldBlog].[dbo].[Post]) AS TAG ON POST.Link = TAG.Link
IMPORTANT NOTE:
This is just a means of "forcing" a relationship between tables without any relationship to each other whatsoever. This is indeed a dangerous thing to do because we are forcing a relationship between the tables based on row number and not an actual key. This should only be used if there is no definite expected output or as a last resort if there is no other way to link two or more unrelated tables where the relationship of each selected column don't matter.