How to create a trigger to modify date column on table with double key - sql

I need to create a trigger that saves the current date&timestamp into the row when it is being inserted or updated.
Table structure
[Period] [char](7) NOT NULL,
[CompanyAlfaCode] [char](2) NOT NULL,
[SamplePercentaje] [int] NULL,
[Usuario] [varchar](50) NULL,
[Date] [Datetime] NULL,
Thank you very much.

Maybe something like:
CREATE TRIGGER DateTrigger ON CompanySampleConfig
AFTER INSERT,UPDATE
AS
BEGIN
UPDATE CompanySampleConfig SET [Date] = current_timestamp
WHERE EXISTS
(SELECT '' FROM inserted
WHERE CompanySampleConfig.[Period] = inserted.[Period]
AND CompanySampleConfig.[CompanyAlfaCode] = inserted.[CompanyAlfaCode]
END

Related

Cannot update a timestamp column

I was recommended the following stored procedure to audit a login table.
CREATE PROCEDURE ApplicationLogin
#Username NVARCHAR(255),
#IpAddress NVARCHAR(255)
AS
BEGIN
DECLARE #UserID INT;
BEGIN TRANSACTION;
SET #UserID = (SELECT UserID FROM User WHERE Username = #Username);
IF #UserID > 0
BEGIN
UPDATE User
SET LastLogin = GETDATE()
WHERE UserID = #UserID;
END
INSERT INTO UserLogger (Username, UserID, TimeStamp)
VALUES (#Username, #UserID, #Timestamp);
COMMIT TRANSACTION;
SELECT #UserID
END
However I can't make it work for some syntax errors that I can't figure out.
The User table looks like this:
CREATE TABLE [dbo].[User]
(
[UserID] [INT] IDENTITY(1,1) NOT NULL,
[UserName] [VARCHAR](50) NOT NULL,
[Enabled] [BIT] NOT NULL,
[LastLogin] [TIMESTAMP] NOT NULL,
PRIMARY KEY CLUSTERED ([UserID] ASC)
)
The Audit table looks like this:
CREATE TABLE [dbo].[UserLogger]
(
[UserID] [INT] IDENTITY(1,1) NOT NULL,
[UserName] [VARCHAR](50) NOT NULL,
[Name] [VARCHAR](100) NULL,
[TS] [TIMESTAMP] NULL,
[IpAddress] [NCHAR](10) NULL
) ON [PRIMARY]
I get an error
Cannot update a timestamp column
which I don't see why.
Any idea?
timestamp is not what you think it is. It is some sort of internal representation of the row address. Here is an explanation.
Use datetime or datetime2 to fix your problem.
This is made all the more confusing, because CURRENT_TIMESTAMP doesn't return a timestamp.

How to update my table where updated columns names stored in another table in SQL Server

I have table User with n columns that stores user information in it.
I have another table User_Edit_Changes that I use to temporarily store changes to table User in it so that after admin confirmation I update the actual table User with new values.
In table User_Edit_Changes, I stored which user column requested for update and what is new value for that. How to write a dynamic query to get just changed value columns and new value from User_Edit_Changes and update the User table?
here is my sample create table command ,
teacher stores infos,
Tbl_ProfessorRequest stores edit change request,
Tbl_ProfessorEditInfoFields stores which fileds teacher request to edit
CREATE TABLE [dbo].[Teacher](
[code_ostad] [numeric](18, 0) NOT NULL,
[name] [varchar](30) NULL,
[family] [varchar](40) NOT NULL,
[namep] [varchar](30) NULL,
[idmadrak] [numeric](18, 0) NULL,
[namemadrak] [varchar](50) NULL,
[idresh] [numeric](18, 0) NULL,
[nameresh] [varchar](50) NULL,
[martabeh] [numeric](18, 0) NULL,
[namemartabeh] [varchar](30) NULL,
[nahveh_hamk] [numeric](18, 0) NULL,
CREATE TABLE [Request].[Tbl_ProfessorRequest](
[ProfessorRequestID] [int] IDENTITY(1,1) NOT NULL,
[Code_Ostad] [int] NULL,
[RequestTypeID] [bigint] NULL,
[RequestLogID] [bigint] NULL,
[CreateDate] [nvarchar](10) NULL,
[Note] [nvarchar](1000) NULL,
[term] [nvarchar](8) NULL,
[ProfessorMessage] [nvarchar](1000) NULL,
[Erae_Be] [nvarchar](100) NULL,
[ChangeSet] [int] NULL,
[isdeleted] [bit] NOT NULL,
[ScanImageUrl] [nvarchar](300) NULL,
CREATE TABLE [Request].[Tbl_ProfessorEditInfoFields](
[Id] [int] IDENTITY(1,1) NOT NULL,
[code_ostad] [int] NOT NULL,
[teacher_Column_Name] [nvarchar](200) NULL,
[OldValue] [nvarchar](200) NULL,
[NewValue] [nvarchar](200) NULL,
[State] [int] NOT NULL,
[ProfessorRequestID] [int] NOT NULL,
I'd say you have 3 options:
Handle the logic of updates outside the database, in what ever your application is built with. That's most likely the easiest way, since this kind of dynamic handling is not what databases are good at.
Build a dynamic SQL clause based on the contents of User_Edit_Changes. Loop through the changes in the table, construct an update statement into a variable and use sp_executesql to execute it. With cursor the code should be something like this:
set #params = N'#NewValue varchar(100)'
fetch next from yourcursor into #FieldName, #NewValue
while ##FETCH_STATUS = 0 begin
set #sql = 'update User set ' + #FieldName + ' = #NewValue'
exec sp_executesql #sql, #params, #NewValue = #NewValue
fetch next from yourcursor into #FieldName, #NewValue
end
Create static SQL statements for updating each of the columns. You can build something like this:
update U
set U.UserName = C.NewValue
from
User U
join User_Edit_Changes C on U.UserId = C.UserId
where
C.FieldName = 'UserName'
For this you of course need to have similar statements for each of your columns. You could build one massive update query with pivot or max+case, but handling the old and new values gets pretty complex.

SQL Check Constraint with User Defined Function

I am troubleshooting an issue seen in our sql server database recently.
Table 1 has a calculated bit column based off of a user defined function which checks if a record exists in another table and evaluates to 0 if not.
Table 2 is the table searched by the function for Table 1. Table 2 also has a check constraint using a function to see if the bit field in Table 1 is set to 1.
This seems like a circular dependency. The problem is that when inserting a batch of records into Table 2, the constraint fails. Inserting these same records 1 by 1 allows all of the inserts to go through. I can't for the life of me figure out why batch inserts cause it to fail. Any help is appreciated.
CREATE TABLE [dbo].[tPecosPriceCheckStoreSubcategory](
[PecosPriceCheckID] [int] NOT NULL,
[StoreID] [int] NOT NULL,
[SubcategoryID] [int] NOT NULL,
[UndirectedExpectedScans] [int] NULL,
[PriceMin] [decimal](8, 2) NULL,
[PriceMax] [decimal](8, 2) NULL,
[PastPriceVariancePercent] [decimal](5, 2) NULL,
[ChangeDate] [datetime] NOT NULL,
[IsUndirected] [bit] NOT NULL,
[IsDirected] AS ([dbo].[fnPecosPriceCheckStoreSubcategoryIsDirected]([PecosPriceCheckID],[SubcategoryID])),
CONSTRAINT [PK_tPecosPriceCheckStoreSubcategory] PRIMARY KEY CLUSTERED
(
[PecosPriceCheckID] ASC,
[StoreID] ASC,
[SubcategoryID] ASC
)
ALTER TABLE [dbo].[tPecosPriceCheckStoreSubcategory] ADD CONSTRAINT [DF_IsUndirected] DEFAULT ((0)) FOR [IsUndirected]
GO
CREATE FUNCTION [dbo].[fnPecosPriceCheckStoreSubcategoryIsDirected]
(
#PecosPriceCheckID int,
#SubcategoryID int
)
RETURNS bit
AS
BEGIN
declare #isDirected bit
set #isDirected = 0
if (exists (select 1 from tPecosDirectedPriceCheckItem where PecosPriceCheckID = #PecosPriceCheckID and SubcategoryID = #SubcategoryID ))
begin
set #isDirected = 1
end
return #isDirected
END
CREATE TABLE [dbo].[tPecosDirectedPriceCheckItem](
[ID] [int] IDENTITY(1,1) NOT NULL,
[PecosPriceCheckID] [int] NOT NULL,
[PecosItemID] [int] NOT NULL,
[ItemSortOrder] [int] NOT NULL,
[SubcategoryID] [int] NOT NULL,
[ChangeDate] [datetime] NULL,
CONSTRAINT [PK_tPecosDirectedPriceCheckItem] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
ALTER TABLE [dbo].[tPecosDirectedPriceCheckItem] WITH NOCHECK ADD CONSTRAINT [CK_tPecosDirectedPriceCheckItem_CheckPriceCheckSubcategoryDirected] CHECK (([dbo].[fnCheckDirectedItemPriceCheckSubcategory]([PecosPriceCheckID],[SubcategoryID])=(0)))
GO
ALTER TABLE [dbo].[tPecosDirectedPriceCheckItem] CHECK CONSTRAINT [CK_tPecosDirectedPriceCheckItem_CheckPriceCheckSubcategoryDirected]
GO
CREATE FUNCTION [dbo].[fnCheckDirectedItemPriceCheckSubcategory]
(
#PriceCheckID INT,
#SubcategoryID INT
)
RETURNS BIT
AS
BEGIN
DECLARE #isViolation BIT
SET #isViolation =
CASE WHEN EXISTS (SELECT * FROM tPecosPriceCheckStoreSubcategory WHERE SubcategoryID = #SubcategoryID AND PecosPriceCheckID = #PriceCheckID AND IsDirected = 1)
THEN
0
ELSE
1
END
RETURN #isViolation
END

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 can you define a computed column like this?

I have an Equipment table in SQL Server 2008 like this:
CREATE TABLE [dbo].[Equipment](
[EquipmentID] [nchar](10) NOT NULL,
[EquipmentName] [nchar](50) NOT NULL,
[ProducedDate] [date] NOT NULL,
[WarrantyPeriod] [int] NOT NULL,
[SerialNumber] [nchar](20) NOT NULL,
[BrandID] [tinyint] NOT NULL,
CONSTRAINT [PK_Equipment] PRIMARY KEY CLUSTERED
)
I want to have a computed column WarrantyStatus that will return either Unexpired or Expired when calculating, based on columns ProducedDate and WarrantyPeriod.
This is wrong, but it's what I want:
ALTER TABLE [dbo].[Equipment]
ADD [WarrantyStatus] AS IIF(DATEDIFF(MONTH, [ProducedDate], GETDATE()) < [WarrantyPeriod], "Unexpired", "Expired")
Try:
ALTER TABLE [dbo].[Equipment]
ADD [WarrantyStatus] AS
case when DATEDIFF(MONTH, [ProducedDate], GETDATE()) < [WarrantyPeriod]
then 'Unexpired'
else 'Expired'
end