How to get data from the current row in INSTEAD OF trigger? - sql-server

For example, we have a table named 'Names':
id | name
-----+------
1 | Mary
2 | Sue
3 | John
and this trigger:
CREATE TRIGGER TRG_insofdel
ON Names
INSTEAD OF DELETE
AS
BEGIN
-- here I need to get some data from the current row
END
and then I call
DELETE FROM Names
WHERE id = 1
How can I get Mary's (id == 1) name in the trigger?
What is going on with the 'deleted' table in this case?

The MSDN documentation does explain but it isn't laid out very clearly.
In a trigger, SQL server automatically makes 2 special in-memory tables available to you:
inserted: the data which was added to the table (for insert and update statements)
deleted: the data which was removed from the table (for update and delete statements)
They have the same columns as the actual table, but are completely read-only - you cannot add columns or indexes to them or change the data inside them.
So in your example, to get the name of the person being removed, you can do the following inside the trigger:
DECLARE #name varchar(100);
SELECT #name = name from deleted;
Important note
Be aware tho that if multiple rows were deleted from the table, then deleted will contain multiple rows - the trigger is not called individually once for each row.

Related

problem in instead of delete views in oracle

I have a view as:
select * from ot.vw_rebellionrid;
which is showing me:
full_name is column of trainer table
subject_name is column of subject table
The view has the query:
SELECT full_name, subject_name
FROM ot.trainer, ot.subject;
So,I am learning the instead of delete tigger,so the code for instead of trigger is:
CREATE OR REPLACE TRIGGER ot.io_delete
INSTEAD OF DELETE ON ot.vw_RebellionRid
FOR EACH ROW
BEGIN
DELETE FROM ot.trainer WHERE FULL_NAME = :old.FULL_NAME;
DELETE FROM ot.subject WHERE SUBJECT_NAME= :old.SUBJECT_NAME;
END;
/
So,to execute this trigger,I execute the following statement:
delete from ot.vw_RebellionRid where subject_name='java';
when it is executed,then :
2 rows deleted.
According to my understanding,Since the two rows has subject_name as java the remaining output,I think will be after the deletion:
--------------------------
full_name | subject_ name |
---------------------------
Manish Sharma Oracle |
ashwin Oracle |
---------------------------
But when I executed
select * from ot.vw_RebellionRid ;
then,I got the output as EMPTY TABLE;
Since,there were 4rows,2rows were deleted,but when i again select the view then how I am getting empty table?I should have got remaining two rows.
I think your trigger is working perfectly.
DELETE FROM ot.trainer WHERE FULL_NAME = :old.FULL_NAME;
It will delete 2 rows having name manish and ashwin as both are tagged with java.
The same way,
DELETE FROM ot.subject WHERE SUBJECT_NAME= :old.SUBJECT_NAME;
It will delete subject java from table subject so now table subject will have 1 record remaining i.e.Oracle
Now, your view query will join between 2 tables (trainer table with 0 rows and subject table with 1 rows) so it is producing no result.
You need to understand that,
delete from ot.vw_RebellionRid where subject_name='java';
is deleting total 3 records.
Cheers!!
The problem is that when debugging your problem you didn't follow through. Your INSTEAD OF DELETE trigger certainly deleted SOMETHING, but to determine what was deleted you need to look at the tables underlying the view. If you perform your DELETE statement and then examine the contents of TRAINER and SUBJECT you'll find that the only thing left is the Oracle row in SUBJECT. And if you look at your trigger and think about what you told it to do you'll realize it did exactly what you told it to do, even if that might not have been what you wanted.
dbfiddle here

SQL Server Trigger to alter different table

I’m trying to create a trigger to change the value of a column in table B if it finds the information in a column in table A.
An example of my database is below:
[TableA],
itemID
[TableB],
itemID
itemInStock
Once a user creates an entry in Table A declaring an itemID, the trigger needs to change the TableB.itemInStock column to ‘Yes’
I’m still learning SQL so excuse me if I’ve missed something, let me know if you need any more info.
I understand there are better ways of doing this but I've been told I need to do this using a trigger.
I've attempted a few different things, but as it stands nothing is working, below is the current solution I have however this updates all itemInStock rows to 'Yes', where as I only want the ones to update where the TableB.itemID matches the itemID entered in TableA.
ALTER TRIGGER [itemAvailability] ON [dbo].[TableA] FOR
INSERT
AS
BEGIN
UPDATE [dbo].[TableB] set itemInStock = 'Yes' WHERE
TableB.itemID = itemID
END
Two problems -
you're not looking at the Inserted pseudo table which contains the
newly inserted rows
you're assuming the trigger is called once per row - this is not the
case, the trigger is called once per statement and the Inserted
pseudo table will contain multiple rows - and you need to deal with
that
So, your code should look like this -
ALTER TRIGGER [itemAvailability] ON [dbo].[TableA]
FOR INSERT
AS
UPDATE TB
SET itemInStock = 'Yes'
FROM [dbo].[TableB] TB JOIN inserted I
on TB.itemID = I.itemID

How to safely use current identity as value in insert query

I have a table where one of the columns is a path to an image and I need to create a directory for the record being inserted.
Example:
Id | PicPath |<br>
1 | /Pics/1/0.jpg|<br>
2 | /Pics/2/0.jpg|
This way I can be sure that the folder name is always valid and it is unique (no clash between two records).
Question is: how can I safely refer to the current id of the record being insert? Keep in mind that this is a highly concurrent environment, and I would like to avoid multiple trips to the DB if possible.
I have tried the following:
insert into Dummy values(CONCAT('a', (select IDENT_CURRENT('Dummy'))))
and
insert into Dummy values(CONCAT('a', (select SCOPE_IDENTITY() + 1)))
The first query is not safe, for when running 1000 concurrent inserts I got 58 'duplicate key' exceptions.
The second query didn't work because SCOPE_IDENTITY() returned the same value for all queries as I suspected.
What are my alternatives here?
Try a temporary table to track your inserted ids using OUTPUT clause
INSERT #temp_ids(someval) OUTPUT inserted.identity_column
This will get all the inserted ids from your queries. 'inserted' is context safe.

Update trigger not working correctly

I have two tables abstractDetails and auditAbstractDetails. I have a web form from where a person submits details about abstract (title, background, objective etc.) and it inserts value into abstractDetails table.
Now I have written a trigger so whenever a person updates his Form and submit it again, it should populate new values into abstractDetails as well as it should populate old values and New values in the AuditabstractDetails table ( title,background,objective..... auditTitle,auditBackground.....)
old value should store in AuditabstractDetails tables under the columns title, background etc. and new values will be stored under the columns auditTitle,auditBackground etc.)
here is my trigger:
USE [Abstract]
GO
/****** Object: Trigger [dbo].[trgAuditabstractDetails] Script Date: 09/28/2016 11:45:29 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [dbo].[trgAuditabstractDetails]
ON [dbo].[abstractDetails]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON
delete from AuditabstractDetails where Id IN (SELECT I.Id
FROM Inserted I);
insert into AuditabstractDetails(Id, abstractInfoId, title, background,
objective, design, result, Audittitle, Auditbackground,
Auditobjective, Auditdesign, Auditresult)
-- case 1: ID unchanged
SELECT I.Id, I.abstractInfoId, D.title, D.background, D.objective,
D.design, D.result,
I.title, I.background, I.objective, I.design, I.result
FROM Inserted I
JOIN Deleted D on I.Id=D.Id;
END
GO
after this when I am updating the value of form (title, background etc.) in the abstractDetails table from the backend (from DB by editing the value in abstractDetails table), it is working perfect. But when I am updating it through the form and submitting it, It is updating New values in both columns ( title, auditTitle etc..), It is not storing old values in specific columns , instead it is storing new values in both the columns.
abstractDetails table
===========================================
Id |title | background | Result
-------------------------------------------
1 Abs1 backAbs2 resAbs2
2 Abs2 backAbs2 resAbs2
-------------------------------------------
Expected Result:
AuditabstractDetails table
===============================================
Id |title | background | Result | AuditTitle | auditBackground |auditResult
----------------------------------------------------------------------------
1 Abs1 backAbs2 resAbs2 Audit1 auditback1 auditres1
2 Abs2 backAbs2 resAbs2 Audit2 auditback2 auditres2
----------------------------------------------------------------------------
ActualResult:
AuditabstractDetails table
===============================================
Id |title | background | Result | AuditTitle | auditBackground |auditResult
----------------------------------------------------------------------------
1 Audit1 auditback1 auditres1 Audit1 auditback1 auditres1
2 Audit2 auditback2 auditres2 Audit2 auditback2 auditres2
----------------------------------------------------------------------------
Need help
It sounds like the problem isn't with the trigger, but is with whatever's saving your data. If it works as desired from SQL Server but fails when the UI is making the call, then you need to check the UI to see what's going on. It seems likely that the UI is updating the record more than once. I would test this by removing the delete portion of your trigger and seeing how many rows you end up with in your audit table.

compare and insert only new records to sqlite database

I have sqlite local database. I want to insert only fresh data from remote server to local database.Since there is no time field,it is difficult to insert only new records.How can i acheive this? I require this for my hybrid mobile app. Any helps apperciated..Thanks in advance.
Two tables:
my local db table is
tbl_orders
id name age
1 yyy 30
2 xxx 20
my remote db table is
tbl_orders
id name age
1 yyy 36
2 xxx 20
3 vvv 40
4 zzz 37
In the above the remote table contains additionally two records and also the value in first record(age column) get changed.now i want to insert and update this(i.e 1st,3rd,4th) to my local sqlite table without deleting and reinserting the whole table.
You should add a UNIQUE constrain in id.
Redefining your local table:
CREATE TABLE tbl_orders(UNIQUE id, name, age);
or without redefining table
CREATE UNIQUE INDEX tbl_orders_id ON tbl_orders(id);
With constrain, your updates become a single statement:
INSERT OR REPLACE INTO local.tbl_orders SELECT * FROM remote.tbl_orders;
Your table is replicated in two DB?
If yes, you can do an INSERT with NOT EXISTS clause in WHERE condition. Alternatively, add datetime field in your source table.
Another way:
Add a boolean field in your source DB (fl_sent), populated by a trigger when create a new row in your DB or update them. Default value is false, and when you want to syncronize your DBs your select is based on this field
SELECT * FROM myTable WHERE fl_sent = 0
For a more complete answer please post your tables.
EDIT AFTER COMMENT:
Solution 1:
Add field date in your remote table (source) (if you want, you write a trigger about toggle this field) and then execute your sendable query based on this date.
Solution 2:
Add field flag (fl_sent) set by zero (if you want, you write a trigger about toggle this field) and then execute your sendable query based on this flag.

Resources