SQL Trigger DATETIME Constraint - sql

I need to create a trigger in a SQL table that inserts data that passes a condition, [value] = 2, into a separate table. However, I do not want to insert new data from the same source that occurs in the same half hour.
That is, data with [ID] = 1 is inserted into [table1] and passes [value] = 2. This data is then inserted into [table2]. If [ID] = 1 produces another line of data with [value] = 2 in the same half hour, it should not be inserted into [table2].
Here is what I have so far:
CREATE TRIGGER [dbo].[example_trigger] ON [dbo].[table1]
AFTER INSERT
AS
BEGIN
DECLARE
#alert_ID varchar(MAX),
#alert_created_at datetime2(7),
#alert_value numeric(8,2)
SELECT #alert_ID = INSERTED.ID,
#alert_created_at = INSERTED.created_at,
#alert_value = INSERTED.value FROM INSERTED
IF #alert_value = 2
AND #alert_created_at > DATEADD(minute, 30, (SELECT MAX([alert_created_at]) FROM [table2] WHERE #alert_uid = [alert_uid]))
BEGIN
INSERT INTO table2(alert_uid, alert_created_at, alert_leak_status)
VALUES(#alert_uid, #alert_created_at, #alert_leak_status)
END

Related

(SQL Merge) I am getting duplicates in the table

We have a daily stream where we are getting the list of customers using various products.
I am trying to create a table for the customers where we can track their changes, and at the same time, we can get a distinct list of customers.
The stream contains thousands of records each day. That was the reason we thought we should move from SCD Type 1 to SCD Type 2.
We want to implement this procedure so that it will run each day and get the records from the last day and compare them to the whole table. If the customer has any change, it will mark that row as 0 and get the new row and mark it as 1.
But in this process, I am getting the new records, but I am also getting duplicate data when I am running the stored procedure.
Please guide.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROC [dbo].[sp_UpdateCustomerInfoHistory] AS BEGIN
SET
NOCOUNT ON --Truncate Table [dbo].[CustomerInfoHistory];
DECLARE #TODAY DATE = GETDATE();
DECLARE #YESTERDAY DATE = GETDATE() - 1;
WITH CTE AS (
SELECT
DISTINCT(a.CustomerId) AS CustomerId,
ISNULL(b.[CustomerName], a.[CustomerName]) AS CustomerName,
ISNULL(b.[CurrentDefaultDomain], a.[CustomerName]) AS CurrentDefaultDomain,
ISNULL(b.[CustomerCountryCode], 'Unknown') AS CustomerCountryCode,
ISNULL(b.[HasC], 0) AS HasC,
ISNULL(b.[HasG], 0) AS HasG,
ISNULL(b.[IsV], 0) AS IsV,
ISNULL(
ISNULL(b.[CustomerCreatedDate], a.[ProductCreatedTimeUtc]),
#TODAY
) AS CustomerCreatedDate,
ISNULL(b.[CustomerState], 'Active') AS CustomerState,
ISNULL(b.[CustomerType], 'RegularCustomer') AS CustomerType,
ISNULL(b.[DataCenterProduct], 'Unknown') AS DataCenterProduct,
ISNULL(b.[DataCenterModel], 'Unknown') AS DataCenterModel,
ISNULL(b.[IsTestCustomer], 0) AS IsTestCustomer,
ISNULL(b.[CommunicationLanguage], 'Unknown') AS CommunicationLanguage,
ISNULL(b.[IsInternal], 0) AS IsInternal,
ISNULL(b.[IndustryName], 'N/A') AS IndustryName,
ISNULL(c.MappingID, 0) AS MappingID
FROM
[dbo].[ProductDetails] AS a
LEFT JOIN [Common].[vwdimCustomer_Staging] AS b ON a.CustomerId = b.CustomerId
LEFT JOIN [Common].[vwmapCustomerMappingID_Staging] AS c ON b.CustomerId = c.CustomerId
WHERE a.[TIMESTAMP] = #YESTERDAY
), CTE1 AS (
Select *, BINARY_CHECKSUM(
CustomerId,
CustomerName,
IsTestCustomer,
IsInternal
) AS MKEY
from CTE)
MERGE INTO [dbo].[CustomerInfoHistory] AS T USING CTE1 AS S ON T.[MKEY] = S.[MKEY]
WHEN MATCHED
AND [Current_Flag] = 1
AND T.CustomerName <> S.CustomerName THEN
UPDATE
SET
T.Current_Flag = 0,
T.End_date = #YESTERDAY
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
CustomerId,
CustomerName,
CurrentDefaultDomain,
CustomerCountryCode,
HasC,
HasG,
IsV,
CustomerCreatedDate,
CustomerState,
CustomerType,
DataCenterProduct,
DataCenterModel,
IsTestCustomer,
CommunicationLanguage,
IsInternal,
IndustryName,
MappingID,
Eff_Date,
End_Date,
Current_Flag,
MKEY,
RefreshedDate
)
VALUES
(
S.CustomerId,
S.CustomerName,
S.CurrentDefaultDomain,
S.CustomerCountryCode,
S.HasC,
S.HasG,
S.IsV,
S.CustomerCreatedDate,
S.CustomerState,
S.CustomerType,
S.DataCenterProduct,
S.DataCenterModel,
S.IsTestCustomer,
S.CommunicationLanguage,
S.IsInternal,
S.IndustryName,
S.MappingID,
#YESTERDAY,
'12/31/2099',
1,
S.MKEY,
#TODAY
);
END
I think you can use MERGE in Azure Synapse. It will insert new rows or update old rows based on the primary key value.
For example:
Create table:
CREATE TABLE dbo.CustomerInfoHistory (
CustomerId int NOT NULL,
CustomerName nvarchar(254) NOT NULL,
CurrentDefaultDomain nvarchar(max) NULL
);
GO
ALTER TABLE dbo.CustomerInfoHistory ADD CONSTRAINT PK__kruserpr__6E092EE804688C07 PRIMARY KEY (CustomerId, CustomerName);
GO
Create a Table-valued parameter named dbo.CustomerInfoHistory_type, it will be used in my stored procedure:
create TYPE dbo.CustomerInfoHistory_type AS TABLE(
CustomerId int NOT NULL,
CustomerName nvarchar(254) NOT NULL,
CurrentDefaultDomain nvarchar(max)
)
GO
Create a Stored procedure, it will merge the same records and insert new records based on the primary key:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create PROCEDURE [dbo].[spUpsertCustomerInfoHistory]
#profile dbo.CustomerInfoHistory_type READONLY
AS
BEGIN
MERGE dbo.CustomerInfoHistory AS target_sqldb
USING #profile AS source_tblstg
ON (target_sqldb.CustomerId = source_tblstg.CustomerId and target_sqldb.CustomerName = source_tblstg.CustomerName )
WHEN MATCHED THEN
UPDATE SET
CurrentDefaultDomain = source_tblstg.CurrentDefaultDomain
WHEN NOT MATCHED THEN
INSERT (
CustomerId,
CustomerName,
CurrentDefaultDomain
)
VALUES (
source_tblstg.CustomerId,
source_tblstg.CustomerName,
source_tblstg.CurrentDefaultDomain
);
END
GO
After that, we can execute the stored procedure by following code:
DECLARE #profileVar AS dbo.CustomerInfoHistory_type;
/* Add data to the table variable. */
INSERT INTO #profileVar (CustomerId, CustomerName, CurrentDefaultDomain) values (1, 'tom','wednesday');
exec [dbo].[spUpsertCustomerInfoHistory] #profileVar
That's all.

Create a SQL Trigger to alter multiple rows into another table?

I'm using databases to connect with PowerApps and PowerBI and I had a question about triggers.
I have a table (Table A) that contains three columns: ID, TotalQty & Date. I would like to create a trigger based on the three main row actions: Insert, Delete & Update.
Example: New row is inserted into Table A from PowerApps (ID = 1000000 & TotalQty = 3 & Date = Today)
This should fire the trigger three times to insert a row into Table B (with rows ID, QrderQty, and Date):
ID = 1000000, OrderQty = 1 of 3, Date = Today
ID = 1000000, OrderQty = 2 of 3, Date = Today
ID = 1000000, OrderQty = 3 of 3, Date = Today
Similarly, if the date column is updated on Table A for this row, I need the three corresponding rows to update their respective date values as well. Or if the row in Table A is deleted, I need the three rows to be removed.
Could anybody give me an example query of this?
You need to create a Trigger first this link contains some tutorial on how to create a trigger.
Then according to your question you need to do some kind of loop for generating values for the OrderQty, I have done a while loop in this answer that exists as part of TSQL
Assuming that you create TableA and TableB with following schemas:
create table [dbo].[TableA]
(
ID integer not null,
TotalQty integer not null,
Date Date not null
)
go
create table [dbo].[TableB]
(
ID integer not null,
OrderQty nvarchar(10) not null,
Date Date not null
)
go
You can create the trigger as follows to do the job for you:
CREATE TRIGGER [dbo].[InsertFromAToB]
ON [dbo].[TableA]
AFTER INSERT
AS
BEGIN
Declare #counter as integer;
set #counter=1;
Declare #qty as integer;
set #qty = (Select TotalQty from inserted);
While(#counter <= #qty)
Begin
Insert into TableB(ID,OrderQty,Date) select ID,(CONVERT(nvarchar(10),#counter) + ' of ' + Convert(nvarchar(10),#qty)) as OrderQty,Date From inserted
set #counter=#counter+1;
END
END

Using the identity column to add a value to a computed column

At times I need to store a temporary value to a field. I have a stored procedure that adds it using:
Insert new record first then
SELECT #Record_Value = SCOPE_IDENTITY();
UPDATE ADMIN_Publication_JSON
SET NonPubID = CAST(#Record_Value as nvarchar(20)) + '_tmp'
WHERE RecID = #Record_Value
It simply takes the identity value and adds an '_tmp' to the end. Is there a way that I can create a default value in the table that would do that automatically if I did not insert a value into that field?
The NonPubID column is just a NVARCHAR(50).
Thanks
You could write a trigger, that replaces NULL with that string upon INSERT.
CREATE TRIGGER admin_publication_json_bi
ON admin_publication_json
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE apj
SET apj.nonpubid = concat(convert(varchar(20), i.id), '_tmp')
FROM admin_publication_json apj
INNER JOIN inserted i
ON i.id = apj.id
WHERE i.nonpubid IS NULL;
END;
db<>fiddle
Downside: You cannot explicitly insert NULLs for that column, should that be desired.
Check out NewKey col below:
CREATE TABLE #Table
(
ID INT NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED,
IDValue VARCHAR(1) ,
ModifiedDT DATETIME NULL,
NewKey AS ( CONVERT(VARCHAR(100),ID)+'_Tmp' )
)
INSERT #Table( IDValue, ModifiedDT )
SELECT 'A', GETDATE()
UNION ALL
SELECT 'Y', GETDATE() - 1
UNION ALL
SELECT 'N', GETDATE() - 5
SELECT * FROM #Table

SQL Server 2008: Sql Insert/Update into another table using insertion IDs output from another table

I have a procedure for insert in multiple dependent tables (update in case record exist). I have input parameters as comma separated string which I am reading in table.
After 1st insertion I am getting InsertedIds in another table variable.
I am struggling over how to do insert in 2nd table. I have following input parameters for 2nd table:
Declare #IdsToBeUpdated table (primary key identity pkey, id int) -- values are 1,-1,3,-1
Declare #CommentsTobeInserted table( primary key identity pkey, comment varchar (max)) -- values are 'com1', 'com2', 'com3'
-1 input in table #IdsToBeUpdated depicts insertion for the corresponding rows in all input tables and value other than -1 depicts that records at that pkey value in all other tables (#CommentsTobeInserted table as in example) have to be updated.
So after first insertion I am getting the inserted ids for rows with -1 value. #InsertedIds = 4,5
So my Ids list logically would become.. 1,4,3,5.
But I am stuck now how to insert/update records in second table respectively.
2nd table would be like follows:
Pkey Primary key identity, commentIds(coming from inserted ids and #IdsToBeUpdated), comments.
I have added one more InsertedIds column in #CommentsTobeInserted. If I could fill it with right InsertedId against correct row, I guess I would be able to do insert/update in 2nd table. And where the value is Id in new column I would do insert, where it's null, I would perform update using #IdsToBeUpdated table.
But currently none of my approach is working. I am new to SQL. Any help would be highly appreciated.
Following is some portion of script for better understanding. I have added first insertion script as well.
USE [Demo]
GO
/****** Object: StoredProcedure [dbo].[USP_NewRequest_Insert] Script Date: 2/11/2016 2:50:34 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[USP_NewRequest_Insert]
-----------------------------------
--------- SomeInput parameters
---------for first insertion omitted
--------------------------------
#IdsToBeUpdated varchar(MAX), --Values are 23|-1|32|-1|-1
#CommentList AS VARCHAR(MAX), --Values 'C2'|'C4'|'C5'|'C6'|'C7'
#MCodeList VARCHAR(MAX), --Values 'M2'|'M4'|'M5'|'M6'|'M7'
#CustomerIdsList VARCHAR(MAX), ----Values 'Cust2'|'Cust4'|'Cust5'|'Cust6'|'Cust7'
#ReturnValue AS INT OUTPUT,
------------------Data is in the order it has to be inserted.. where IDs exist in #IdsToBeUpdated, updation would be done. For -1 values, insertion.
AS
BEGIN
BEGIN TRANSACTION
--------------------------Split input strings aand insert in Table variable----------------------------
declare #MCodes Table (pkey int primary key identity, MCode varchar(20))
insert into #MCodes select s.Item from [dbo].UDF_SplitString(#MCodeList, '|') s
declare #CusCodes Table (pkey int primary key identity, CusCode varchar(200))
insert into #CusCodes select s.Item from [dbo].UDF_SplitString(#CustomerIdsList, '|') s
declare #ReqDetailsIds Table (pkey int primary key identity, Id Int)
insert into #ReqDetailsIds select Convert(INT,RTRIM(LTRIM(s.Item))) from [dbo].UDF_SplitString(#IdsToBeUpdated, '|') s
where s.Item is not null and RTRIM(LTRIM(s.Item)) <>''
declare #ProductComments Table (pkey int primary key identity, Comment Varchar(max), insertedId int null)
insert into #ProductComments(Comment) select s.Item from [dbo].UDF_SplitString(#CommentList, '|') s
DECLARE #intErrorCode int;
------------------------------------------------------------------------------------------------------------
-----------------First Insertion which returns inserted IDs for 2nd insertion
------------------------------------------------------------------------------------------------------------------
---Insert/Update product details in [RequestDetails]
Declare #InsertedIDList Table (pkey int primary key identity, ID int); --------Table to read inserted Ids. Used in query below
-----------------------Insert query in case Detail id = -1
INSERT INTO [dbo].[RequestDetails]
[MCode]
,[CustomerIds]
,[ExpectedVolume]------Some parameters coming for first insertion in input
,[StatusCode])
Output INSERTED.ReqDetailId Into #InsertedIDList(ID)
SELECT A.MCode, B.CusCode, E.Vol,1
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id = -1 --If id = -1, insert
---------------------------Update Query for rest records
UPDATE [dbo].[RequestDetails]
SET [MCode] = upd.MCode
,[CustomerIds] = upd.CusCode
,[ExpectedVolume] = upd.ExVol
,[StatusCode] = 1
FROM(
SELECT A.MCode, B.CusCode, E.ExVol, G.Id
FROM #MCodes A
JOIN #CusCodes B ON B.pkey = A.pkey
JOIN #ExpectedVols E ON E.pkey = A.pkey
JOIN #ReqDetailsIds G ON G.pkey = A.pkey
WHERE G.Id <> -1
) upd
WHERE upd.Id = dbo.RequestDetails.ReqDetailId
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
---------------------------------------------------------------------------
----------------------------Now similarly I have to do insert/update in Comments Table. But
----------------------------Comments table has RequestDetails Id column as foreign key. So
----------------------------now the challange is to add the rows with Inserted ID where value was = -1
----------------------------in input. We have got the IDs corresponding to -1 values from above insertion
----------------------------in the #InsertedIDList Table variable
-----------------------------------------------------------------------------------------
----------------------------Following is what I have tried so far. But I am not able to insert
----------------------------correct InsertedId against correct record.
----------------------------------------------------------------------------------------
-----------------------Here I tried to insert the new generated ids against corresponding comments in table variable.
-----------------------So that I can perform insert where value is not null. As NULL would be inserted where new ID has not been created
-----------------------and corresponding updated ID exists in input (Values not equal to -1)
-------------------------------------------------------------------------------------------------
Update #ProductComments set insertedId = i.ID from ---------This query is not working
(select A.pkey, B.id as detailId, row_number() over (order by (select 0)) as row_num from
#ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey) as mappedNewIds right join
#InsertedIDList i on i.pkey = mappedNewIds.row_num
where mappedNewIds.pkey = [#ProductComments].pkey
----Insert in CommentsTable for New Comments against request
---------------------------------
INSERT INTO [dbo].CommentsTable
( ReqDetailId, Comments, CreatedOn )
SELECT A.insertedId, A.Comment, GETDATE()
FROM #ProductComments A
where A.insertedId is not null
-----Update Query
------------------------------------------------------------------------------------------
UPDATE [dbo].[CommentsTable]
SET [ReqDetailId] = upd.Id
,[Comments] = upd.Comment
,[CreatedOn] = GetDate()
FROM(
SELECT A.Comment, B.Id
FROM #ProductComments A
JOIN #ReqDetailsIds B ON B.pkey = A.pkey
WHERE A.insertedId is not null
) upd
WHERE upd.Id = dbo.CommentsTable.ReqDetailId
END
select * from CommentsTable;
---------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
IF(##Error<>0)
BEGIN
SET #intErrorCode = ##Error
GOTO ERROR
END
ELSE
BEGIN
SET #ReturnValue=1
END
COMMIT TRANSACTION
ERROR:
IF (#intErrorCode <> 0) BEGIN
SET #ReturnValue = 0;
ROLLBACK TRANSACTION
END
END

Don't allow null value to update column if already contains data

I have a source that I am pulling data from to update an existing table.
Is a way to update the values in each field only if the source data is not NULL?
You should use ISNULL(#paramA, ColumnA):
UPDATE someTable
set ColumnA = ISNULL(#ParamA, ColumnA)
WHERE
.....
take into consideration that u mentioned if source data is not null then update
--Create a sample table
DECLARE #SAMPLE TABLE
(
SourceID INT IDENTITY(1,1),
SourceData NVARCHAR(255)
)
--Create dummy data
INSERT INTO #SAMPLE VALUES ('SOMETHING')
INSERT INTO #SAMPLE VALUES (NULL)
INSERT INTO #SAMPLE VALUES ('SOMETHING')
--update source data that is not null, this will update entire table
UPDATE #SAMPLE
SET SourceData = 'New Data'
FROM #SAMPLE t1
INNER JOIN (
SELECT * FROM #SAMPLE Where SourceData is not null) t2
ON t1.SourceID = t2.SourceID
OR if you just want to update selected records
--Pass in your variable
DECLARE #SourceID INT
--play around your source id
SET #SourceID = 2
--if the particular id is with null data, then update will never perform
IF EXISTS(SELECT 1 FROM #SAMPLE WHERE SourceID = #SourceID and SourceData is not null)
Update #SAMPLE
set SourceData = 'New Item'
where SourceID = #SourceID