How to track deleted rows from database system versioned table in Azure SQL/SQL Server? - sql

I have system versioned Customer table and need to track if admin user deleted the row ('Tesla') from the table.
CustomerHistory table do get new row for 'Tesla', but it does not explicitly tell if row has been updated or deleted.
I would need advice to create SELECT/INSERT SQL query, which compared Customers and CustomerHistory to check which row has been deleted and insert the row ('Tesla') to CustomersDeleted table.
I have System versioned table:
CREATE TABLE [sales].[Customers](
[Customer_PK] [int] IDENTITY(1,1) NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
) ON [PRIMARY]
GO
It has value '1','100','Tesla' and '2','200','Ford'.
Admin user will deleted 'Tesla' row.
I have History versioned table:
CREATE TABLE [sales].[CustomersHistory](
[Customer_PK] [int] NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
) ON [PRIMARY]
GO
I have third table where I would like to insert rows ('Tesla') that has been removed from Customer table.
CREATE TABLE [sales].[CustomersDeleted](
[Customer_PK] [int] NOT NULL,
[Customer_Id] [smallint] NULL,
[Customer_Name] [nvarchar](150) NULL,
[Deleted_time] [datetime2](7) NULL
) ON [PRIMARY]
GO

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 )

Audit history of sql child table

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
)

update trigger to update records in another table

I have on User_Table
CREATE TABLE [dbo].[User_TB]
(
[User_Id] [varchar](15) NOT NULL,
[User_FullName] [varchar](50) NULL,
[User_Address] [varchar](150) NULL,
[User_Gender] [varchar](10) NULL,
[User_Joindate] [varchar](50) NULL,
[User_Email] [varchar](50) NULL,
[User_Branch] [varchar](50) NULL,
[User_TeamLeader] [varchar](50) NULL,
[User_Department] [varchar](50) NULL,
[User_Position] [varchar](50) NULL,
[TID] [int] NULL
)
Break_Table
CREATE TABLE [dbo].[Break_TB]
(
[Break_Id] [int] IDENTITY(1,1) NOT NULL,
[User_Id] [varchar](15) NOT NULL,
[Date] [date] NULL,
[Break_Time] [int] NULL,
[Status] [varchar](50) NULL,
[Late_time] [int] NULL,
[TL_Id] [varchar](15) NULL,
[start_Time] [time](7) NULL,
[end_Time] [time](7) NULL,
)
Log_Table
CREATE TABLE [dbo].[Log_TB]
(
[User_Id] [varchar](50) NOT NULL,
[First_Login] [time](0) NULL,
[Logout] [time](0) NULL,
[Date] [date] NULL,
[Working_Hrs] [time](0) NULL,
)
Now what am trying to do is that whenever the User_Id from User_Table is Updated , I want trying to update User_Id of Another two tables,
I have written trigger for that
Alter TRIGGER [dbo].[updateUserId] on [dbo].[User_TB]
FOR Update
AS
declare #Branch_Name varchar(50),
#User_Id varchar(15)
select #User_Id = i.User_Id from inserted i;
Update Break_TB set User_Id = #User_Id where User_Id = #User_Id;
Update Log_TB set User_Id = #User_Id where User_Id = #User_Id;
But
It only updates records from Break_TB, It not works for Log_TB
Am not very good at triggers, if am wrong please Help me.
You would need something like this - a set-based solution that takes into account that in an UPDATE statement, you might be updating multiple rows at once, and therefore your trigger also must deal with multiple rows in the Inserted and Deleted tables.
CREATE TRIGGER [dbo].[updateUserId]
ON [dbo].[User_TB]
FOR UPDATE
AS
-- update the "Break" table - find the rows based on the *old* User_Id
-- from the "Deleted" pseudo table, and set it to the *new* User_Id
-- from the "Inserted" pseudo table
SET User_Id = i.User_Id
FROM Inserted i
INNER JOIN Deleted d ON i.TID = d.TID
WHERE
Break_TB.User_Id = d.User_Id
-- update the "Log" table - find the rows based on the *old* User_Id
-- from the "Deleted" pseudo table, and set it to the *new* User_Id
-- from the "Inserted" pseudo table
UPDATE Break_TB
SET User_Id = i.User_Id
FROM Inserted i
INNER JOIN Deleted d ON i.TID = d.TID
WHERE
Break_TB.User_Id = d.User_Id
This code assumes that the TID column in the User_TB table is the primary key which remains the same during updates (so that I can join together the "old" values from the Deleted pseudo table with the "new" values after the update, stored in the Inserted pseudo table)

how to Deleting Duplicates and updating "one to many" related table?

I have searched, and perhaps I am not asking the question correctly.
I have inherited a nasty database and am trying to "normalize" it.
I have broken one table into two: Owners and Buildings
And now I have two One to One tables.
I know how to deleted duplicate records (in the Owners table) but I do not know how to then update the "one to many" related table.
I have one table "Owners" and one table "Owners(one) to Buildings(many)"
"Owners" Table schema:
CREATE TABLE
[dbo].[tbl_BuildingOwners]
(
[OwnerID] [int] IDENTITY(1,1) NOT NULL,
[OwnerName] [nvarchar](255) NULL,
[OwnerAddress1] [nvarchar](255) NULL,
[OwnerAddress2] [nvarchar](255) NULL,
[OwnerAddress3] [nvarchar](255) NULL,
[OwnerCity] [nvarchar](255) NULL,
[OwnerState] [nvarchar](255) NULL,
[OwnerZip] [float] NULL,
[OwnerZipExt] [float] NULL,
[OwnerPhone] [nvarchar](255) NULL,
[OwnerFax] [nvarchar](255) NULL
)
"Owners(one) to Buildings(many)" Relational Table schema:
CREATE TABLE
[dbo].[BuildingOwnerID]
(
[OwnerRelationshipID] [int] IDENTITY(1,1) NOT NULL,
[OwnerID] [int] NOT NULL,
[FileNumber] [nvarchar](255) NOT NULL
)
I need to delete the duplicates in the BuildingOwners table and update the OwnerID in the BuildingOwnerID table to the DISTINCT OwnerID that is left in the BuildingOwners table.
I hope this made sense.
I have already tried this but could not make it work for me. Lastly, I can use either SQL sever or MS Access which ever is easier.
To remove duplicate you can use below query (sample query to remove duplicate state entries [duplicate by Country and State])....
WITH dupDel
AS ( SELECT ROW_NUMBER() OVER ( PARTITION BY country, STATE ORDER BY country ) AS RowNum
FROM tblTest
)
DELETE FROM dupDel
WHERE RowNum > 1