Select data, setting a calculated value into a column - sql

I'm selecting data from a table within a trigger (FOR UPDATE). Some rows I'm selecting have been updated by a transaction, that initiated the trigger, and some rows are not. I'd like to write somewhere in the dataset a flag for every row, which value would be calculated as "id IN (SELECT [id] FROM INSERTED)". This flag would show, is a row updated with the last transaction or not.
Is it possible in SQL?
Sure, I can do 2 separate queries, with 2 different conditions, but the trigger perfomance is real bottleneck...

Here's an example for SQL Server:
if object_id('TriggerTest') is not null
drop table TriggerTest
create table TriggerTest (id int identity, name varchar(50), inLastUpdate bit)
insert TriggerTest (name) values ('joe'), ('barrack'), ('george'), ('dick')
go
create trigger dbo.TriggerTestDelete
on TriggerTest
after update
as begin
declare #date datetime
set #date = GETDATE()
update dbo.TriggerTest
set inLastUpdate =
case when id in (select id from inserted) then 1
else 0
end
end
go
update TriggerTest set name = name where id in (1,2)
update TriggerTest set name = name where id in (1,3)
select * from TriggerTest
This prints:
id name inLastUpdate
1 joe 1
2 barrack 0
3 george 1
4 dick 0

Related

SQL Server trigger if update() with condition

I have a table in SQL Server that has 3 columns: ID, NAME, VALUE.
This table has 2 rows with ID=1 and ID=2.
(The value of ID doesn't change).
Every moment of time the value of column VALUE changes. Every time the column VALUE changes, I want to insert this updated value into a table (Device1 for ID=1, Device1 for ID=2).
I created a trigger for updating as if update(VALUE) begin...but it doesn't do the work.
Is there a way to add a condition in if update(VALUE) to work in each row
I used this query
Create Trigger insertIntoDevices
On ITEMS
For Update
As
If Update(VALUE)
Begin
Insert Into table device1
Where ID = 1
Insert Into table device2
Where ID = 2
End
With this query each update in column VALUE inserts VALUE into device1 and device1 and that duplicates values in my tables device1 and device2.
Table creation on the below ;
CREATE TABLE TestTable(
ID INT IDENTITY(1,1),
Name VARCHAR(5),
VALUE NVARCHAR(50)
)
GO
CREATE TABLE device1(
VALUE NVARCHAR(50)
)
GO
CREATE TABLE device2(
VALUE NVARCHAR(50)
)
GO
Insertion for ID=1 and ID=2
GO
INSERT INTO TestTable(Name,Value)
VALUES('Test1','test1'),('TEST2','test2')
Firstly,To find new values for each row you can use 'inserted' but it can be include non-changed data. For example: ID =1,Name='test1' and VALUE='test1' and updation of name column will be also included in inserted.
Secondly,To find old values for each row you can use 'deleted'.
After that we find the values that only includes updation for VALUE.
To Sump Up,
Finding Inserted rows and deleted rows will give us the result of each rows new and old values. We used intersection (INNER JOIN ) to find only changed values.
CREATE TRIGGER [dbo].[insertIntoDevices]
ON [dbo].[TestTable]
AFTER UPDATE
AS
BEGIN
DECLARE #InsertedTable table (
InsertedID INT,
InsertedName VARCHAR(5),
InsertedVALUE NVARCHAR(50)
)
DECLARE #DeletedTable table (
DeletedID INT,
DeletedName VARCHAR(5),
DeletedVALUE NVARCHAR(50)
)
INSERT INTO #InsertedTable(InsertedID,InsertedName,InsertedVALUE)
SELECT ID,[Name],[Value] FROM inserted;
INSERT INTO #DeletedTable(DeletedID,DeletedName,DeletedVALUE)
SELECT ID,Name,Value FROM deleted;
INSERT INTO device1(VALUE)
SELECT UpdatedValue = it.InsertedVALUE
FROM #InsertedTable as it
INNER JOIN #DeletedTable as dt ON it.InsertedID = dt.DeletedID AND ISNULL(dt.DeletedVALUE,'') <> ISNULL(it.InsertedVALUE,'')
WHERE it.InsertedID = 1
INSERT INTO device2(VALUE)
SELECT UpdatedValue = it.InsertedVALUE
FROM #InsertedTable as it
INNER JOIN #DeletedTable as dt ON it.InsertedID = dt.DeletedID AND ISNULL(dt.DeletedVALUE,'') <> ISNULL(it.InsertedVALUE,'')
WHERE it.InsertedID = 2
END
To test I used the updation queries on the below;
--Example 1
UPDATE TestTable
SET Value='selam'
WHERE ID = 1
--Example 2
UPDATE TestTable
SET Value='hi'
WHERE ID = 2

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

ignoring last value if its the same as current value

I have an table where i would like to query the following:
The data comes in batches . This data is combined with an id.
This ID only gets send ones when the new batch comes in. After that the ID only changes when there is a new batch . In the mean time the value stays null
What i need to do is if new data comes in and it has the same id as the previous batch i have to continue the insert with null in the id field instead of pushing a new row with the same id value.
Beneath is a simplistic view of the table
ID Values
1 10
null 20
null 20
null 20
null 20
2 20
null 20
null 20
null 20
null 20
1 20
null 20
If you could help me point in a directions that would help me a lot.
Maybe to clearify the id value is a set of tags. So there are some definied tags(100 or more) and when a new batch comes the batch gets a tag with it. And if that tag is the same as the previous the null has to continue instead of inserting the same tag
You'll need to add an identity field (or a timestamp) in order to be able to query the latest ID.
ALTER TABLE MyTable ADD MyIdent INT IDENTITY(1, 1) NOT NULL
Then on your insert (if your Id value is NULL) you can call
INSERT INTO MyTable (Id, Values)
SELECT TOP 1 Id, #ValuesVariable
FROM MyTable
WHERE Id IS NOT NULL
ORDER BY MyIdent DESC
This below Sp may helps to inert data try this
IF OBJECT_ID('tempdb..#Temp')IS NOT NULL
DROP TABLE #Temp
CREATE TABLE #Temp (ID INT,[Values] INT)
CREATE PROCEDURE usp_Insert
(
#Id INT,
#Values INT
)
AS
BEGIN
IF NOT EXISTS (SELECT 1 FROM #Temp WHERE ID = #ID)
BEGIN
INSERT INTO #Temp(ID,[Values])
SELECT #Id,#Values
END
ELSE
INSERT INTO #Temp(ID,[Values])
SELECT NULL,#Values
END
EXEC usp_Insert 2,12
SELECT * FROM #Temp

How to auto increment for a coulmn in sql server limited to partition [duplicate]

Database question here.
Is it possible to make an autoincrement on a secondary or a thirtiary ID?
I need to make something versionbased, so imagine this:
ID Phrase PhraseID PhraseVersion
1 "" 1 1
2 "" 1 2
3 "" 1 3
4 "" 2 1
PhraseID can be the same number, when added to the database.
If the PhraseID exists, i want PhraseVersion to autoincrement in number.
If the PhraseID doesnt exist, i want PhraseVersion to start over, counting from 1.
I this possible?
I would go with a computed column for PhraseVersion, that will take the count of rows with the same PhraseID and Id lower or equal to the current row.
To do that, you need to create a UDF to calculate the PhraseVersion:
CREATE FUNCTION dbo.GetPhraseVersion (
#PhraseId int,
#id int
)
RETURNS INT
AS
BEGIN
RETURN (
SELECT COUNT(*)
FROM T
WHERE PhraseId = #PhraseId
AND Id <= #id
)
END
GO
Then, Create the table with the computed column:
CREATE TABLE T
(
id int identity(1,1),
PhraseId int,
PhraseVersion as dbo.GetPhraseVersion(PhraseId, id)
)
GO
Now for the test - insert 4 records:
INSERT INTO T (PhraseId) VALUES(1),(1),(1),(2)
Select:
SELECT *
FROM T
Results:
id PhraseId PhraseVersion
1 1 1
2 1 2
3 1 3
4 2 1
You can see a live demo on rextester.
This can be accomplished via an insert trigger on the table:
CREATE TABLE Phrases (
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
PhraseID INT NOT NULL DEFAULT(0),
PhraseVersion INT NOT NULL DEFAULT(0))
GO
-- ==========================================================================================
-- Author: Donna Landy
-- Create Date: 21 Nov 2019
-- Purpose: To populate the PhraseVersion column (subordinate numeric key) on Insert
-- Note: Must cater for >1 row being inserted when this trigger is called
-- Strategy: Construct a temp table with the rows we need to consider, then update one row at a time
-- ==========================================================================================
CREATE TRIGGER Phrases_Insert ON Phrases AFTER INSERT
AS
BEGIN
DECLARE #ID INT
DECLARE #PhraseID INT
DECLARE #PhraseVersion INT
DECLARE #i INT
DECLARE #iMax INT
-- Create and populate temp table
IF OBJECT_ID('tempdb..#phrases', 'U') IS NOT NULL DROP TABLE #phrases
CREATE TABLE #phrases (i INT IDENTITY(1,1) PRIMARY KEY, ID INT, PhraseID INT)
INSERT INTO #phrases (ID, PhraseID) SELECT ID, PhraseID FROM inserted
-- Scan temp table
SET #i=1
SELECT #iMax=MAX(i) FROM #phrases
WHILE #i <= #iMax BEGIN
-- Fetch PhraseID & PhraseVersion for the row we are going to update
SELECT #ID=ID, #PhraseID=PhraseID FROM #phrases WHERE i=#i
-- Find the highest current Ref
SELECT #PhraseVersion=ISNULL(MAX(PhraseVersion),0) FROM Phrases WHERE PhraseID=#PhraseID
-- Update the row
UPDATE Phrases SET PhraseVersion=#PhraseVersion+1 WHERE ID=#ID
-- Increment loop counter
SET #i+=1
END
-- Remove temp table
IF OBJECT_ID('tempdb..#phrases', 'U') IS NOT NULL DROP TABLE #phrases
END
GO

How to capture the unique identifier after the insert [duplicate]

This question already has answers here:
How do I return a new IDENTITY column value from an SQLServer SELECT statement?
(7 answers)
Closed 8 years ago.
I have to create new email records in an existing table in the joining table I would like to update a field that would denote that this is a new record.
Example:
INSERT INTO dbo.email.email (dbo.email.eml_address, dbo.email.eml_customer_key)
SELECT new_email, new_customer_key
FROM NEW_TABLE
Update dbo.email_ext
Set dbo.email_ext.new_eml = '1'
Where dbo.email_ext.eml_key_ext = 'Recently create key from insert statement shown above'
You'll want to use the SCOPE_IDENTITY() value, this will contain the ID of the record just created, but only one.
Assuming you're handling ONE record:
DECLARE #ID INT
INSERT INTO dbo.email (eml_address, eml_customer_key)
SELECT new_email, new_customer_key
FROM NEW_TABLE
SET #ID = SCOPE_IDENTITY()
Update dbo.email_ext
Set new_eml = '1'
Where eml_key_ext = #ID
If you're inserting multiples you need to output the list into a table (in this case a table variable) and you can update them all at once.
DECLARE #myIDs TABLE (NEWID INT)
INSERT INTO dbo.email (eml_address, eml_customer_key)
OUTPUT inserted.ID INTO #myIDs
SELECT new_email, new_customer_key
FROM NEW_TABLE
Update t
Set new_eml = '1'
from dbo.email_ext t
join #myIDs m
on t.eml_key_ext = m.ID
Use an OUTPUT clause to capture autogenerated ids/guids/defaults/etc.
CREATE TABLE #test (
id int identity(1,1) primary key,
uid uniqueidentifier DEFAULT NEWID(),
value varchar(max)
)
INSERT #test (value)
OUTPUT inserted.*
SELECT 'test'
id guid value
----------- ------------------------------------ ---------
1 72B70577-2679-4C2A-A575-62D30807B9D2 test
(1 row(s) affected)