I have requirement like, I have to insert the records whenever for one BID, one SID, if the execdate and stopbilldate exist, then I need to insert new record with NULL as Stopbilldate
sample example is as follows:
Sno BID SID LID Comapny Execdate StopBilldate
5 BLDG100 C 6500 Cole 1/5/2012 5/29/2012
6 BLDG100 C 000000 Vacant 5/30/2012 NULL
You can do this with a TRIGGER on your table. A trigger is a kind of stored procedure that will execute when an event occurs.
Here is a sample of what you could place on your table:
CREATE TRIGGER [trg_yourTable]
ON [yourTable]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for trigger here
INSERT INTO yourTable (bid, sid, lid, company, execdate, stopbilldate)
SELECT i.bid, i.sid, 0, 'Vacant', DATEADD(day, 1, i.stopbilldate), null
FROM inserted i
WHERE i.bid is not null
and i.sid is not null
END
When you INSERT data in the table, this will run and INSERT the additional row that you want added to the table.
Related
I have the following query:
INSERT INTO LOAN (MemberSSN, VolumeID, LoanDate)
OUTPUT inserted.MemberSSN, inserted.VolumeID, inserted.LoanDate
VALUES ('488-40-', 2, GETUTCDATE())
I want a trigger that, upon insertion in the LOAN table, the following query is executed - an INSERT into the VOLUME_VOLUME_STATUS table:
INSERT INTO VOLUME_VOLUME_STATUS (VolumeID, StatusID, DateCreated)
VALUES (>>previouslyInsertedVolumeID<<, 2, getutcdate())
As you can see, I am unsure how to tell SQL the VolumeID that has just been inserted, which is 2.
Below is the trigger that I wrote:
CREATE TRIGGER LoanStatusUpdate_OnLoaning
AFTER INSERT
ON LOAN
BEGIN
INSERT INTO VOLUME_VOLUME_STATUS (VolumeID, StatusID, DateCreated)
VALUES (>>previouslyInsertedVolumeID<<, 2, getutcdate())
END
Therefore, what should be passed as the value for the VolumeID column so that the parameter is the one from the INSERT prior to the trigger being activated?
Figured some errors in the previous trigger. Here's the one with fixed syntax errors:
CREATE TRIGGER LoanStatusUpdate_OnLoaning
ON LOAN
AFTER INSERT
AS
INSERT INTO VOLUME_VOLUME_STATUS (VolumeID, StatusID, DateCreated)
VALUES (New.VolumeID, 2, getutcdate())
GO
I think you just want to use inserted:
CREATE TRIGGER LoanStatusUpdate_OnLoaning ON LOAN AFTER INSERT
BEGIN
INSERT INTO VOLUME_VOLUME_STATUS (VolumeID, StatusID, DateCreated)
SELECT i.VolumeId, 2, getutcdate()
FROM inserted i;
END;
You can also pull the StatusId from inserted as well. And DateCreated could be set as a default value in VOLUME_VOLUME_STATUS.
Part1 on View
1-1) Create a view named VDept_Headcount that reports headcount for each department.
The report includes 3 columns as follow:
Dept_Name, Dept_Number, No_Emp.
Include all the departments.
Show the content of the view through SQL (Select * from VDept_Headcount;)
USE COMPANY
GO
--1-1) Create a view named VDept_Headcount that reports headcount for each department.
CREATE VIEW VDept_Headcount(Dept_Name, Dept_Number, No_Emp)
AS
SELECT d.DNAME, d.DNUMBER, COUNT(e.DNO)
FROM DEPARTMENT d LEFT OUTER JOIN EMPLOYEE e ON e.DNO = d.DNUMBER
GROUP BY d.DNAME, d.DNUMBER;
GO
SELECT *
FROM VDept_Headcount;
USE COMPANY
GO
--Add yourself into Employee
INSERT INTO EMPLOYEE
VALUES('Dan', NULL, 'Chan', '122345687', '13-Nov-1948', '323 Williams Ct, Columbus, OH', 'M', 55000, '987654321', 5);
SELECT *
FROM VDept_Headcount;
My question is there a different way to replace null value if I want add things back in? Can I use a blank value?
You should detect if it's an INSERT OR DELETE , try this :
CREATE TRIGGER AuditEmp_Trigger
ON YOUR_TABLE
AFTER INSERT , DELETE
AS
if (SELECT COUNT(*) FROM INSERTED ) > 0 AND (SELECT COUNT(*) FROM DELETED) =0
BEGIN
INSERT INTO destination_table SELECT * FROM INSERTED;
END
if (SELECT COUNT(*) FROM INSERTED ) = 0 AND (SELECT COUNT(*) FROM DELETED) >0
BEGIN
INSERT INTO destination_table SELECT * FROM DELETED;
END
GO
If you need to check just the columns updated you can use COLUMNS_UPDATED ()
Your trigger needs to be able to handle multiple rows in the Inserted and Deleted pseudo table, since if your UPDATE statement affects 10 rows, the trigger is called ONCE, but these pseudo table contain 10 rows each. You cannot just try to "select" the values from those table - you'd get one arbitrary row, and all other would be ignored and not handled.
You need to write your triggers in a set-based fashion, and in the case of UPDATE, join the two pseudo tables on the primary key of the table they're attached to:
CREATE TRIGGER dbo.EMPLOYEE_FKDno_UPDATE
ON dbo.DEPARTMENT FOR UPDATE
AS
BEGIN
INSERT INTO dbo.Audit_Emp_Record (date_of_change, old_Lname, new_Lname, old_dno, new_dno, old_ssn, new_ssn)
SELECT
GETDATE(), d.Name, i.Name, d.Number, i.Number, d.Mgr_Ssn, i.Mgr_Ssn
FROM
Inserted i
INNER JOIN
Deleted d ON i.PrimaryKey = d.PrimaryKey
In case of the DELETE, you'll just have only the Deleted table with the "old" values - so you'll need something like this:
CREATE TRIGGER dbo.EMPLOYEE_FKDno_DELETE
ON dbo.DEPARTMENT FOR DELETE
AS
BEGIN
INSERT INTO dbo.Audit_Emp_Record (date_of_change, old_Lname, new_Lname, old_dno, new_dno, old_ssn, new_ssn)
SELECT
GETDATE(), d.Name, NULL, d.Number, NULL, d.Mgr_Ssn, NULL
FROM
Deleted d
And in case of the INSERT, you'll just have only the Inserted table with the new values - so you'll need something like this:
CREATE TRIGGER dbo.EMPLOYEE_FKDno_DELETE
ON dbo.DEPARTMENT FOR DELETE
AS
BEGIN
INSERT INTO dbo.Audit_Emp_Record (date_of_change, old_Lname, new_Lname, old_dno, new_dno, old_ssn, new_ssn)
SELECT
GETDATE(), NULL, i.Name, NULL, i.Number, NULL, i.Mgr_Ssn
FROM
Inserted i
I Have the following scenario:
CREATE TABLE dbo.Orders
(
OrderID int IDENTITY (1,1) NOT NULL
, OrderVersion int DEFAULT(1)
, Customer varchar(30)
, ScheduleDate date
, PaymentOption int
);
CREATE TABLE dbo.OrdersItems
(
OrderItemsID int IDENTITY (1,1) NOT NULL
, OrderID int
, Product varchar(100)
, Qty int
, value decimal(18,2)
);
CREATE TABLE dbo.logOrders
(
OrderID int NOT NULL
, OrderVersion int DEFAULT(1)
, Customer varchar(30)
, ScheduleDate date
, PaymentOption int
);
CREATE TABLE dbo.logOrdersItems
(
OrderItemsID int NOT NULL
, OrderID int
, Product varchar(100)
, Qty int
, value decimal(18,2)
);
-- Insert values into the table.
INSERT INTO dbo.Orders (Customer , ScheduleDate, PaymentOption)
VALUES ('John', 2016-09-01, 1);
INSERT INTO dbo.OrdersItems( OrderId, Product, Qty, Value)
VALUES (1, 'Foo', 20, 35.658),
(1, 'Bla', 50, 100)
(1, 'XYZ', 10, 3589)
First Statement
UPDATE Orders set ScheduleDate = 2016-10-05 WHERE OrderId = 1
Second Statement
Delete From OrdersItems WHERE OrderItemsID = 2
UPDATE OrdersItems set Qty = 5 WHERE OrderItemsID = 1
Third Statement
Update Orders set PaymentOption = 2 WHERE OrderId = 1
Update OrdersItems set Value = 1050 WHERE OrderItemsID = 3
I am trying to figure out how to make a trigger that after each one of the Statements Sample above Insert on the log Tables the data before the changing. And setting the OrderVersion to OrderVersion + 1 on table Orders.
So on the log Tables I will have all versions after the later one.
Is it possible to make a single trigger to monitor both tables and execute getting the original data before the UPDATE, DELETE , INSERT statement to get the original data and INSERT on the logTables ?
Here comes a sample to explain better what result I want.
This is the Initial Data on table Orders and OrdersItems
If I make an Update on Orders ( any column ) or Make an Update,Insert,Delete on OrdersItems I need to Insert on respectively logTables the data on the image.
And with this I'll have on logOrders and logItems the original data and on the Orders and Items the altered data.
I Hope I could explain better what I mean.
You will need two triggers. The trigger for the Orders table handles Orders table update/delete. The trigger for the OrdersItems table does the same for OrdersItems. The triggers look like this:
For the Orders table:
CREATE TRIGGER dbo.Orders_trigger
ON dbo.Orders
AFTER DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.logOrders
SELECT * FROM DELETED;
INSERT INTO dbo.logOrdersItems
SELECT oi.* FROM OrdersItems oi
WHERE oi.OrderID IN (SELECT OrderId FROM DELETED);
END
GO
For OrdersItems:
CREATE TRIGGER dbo.OrdersItems_trigger
ON dbo.OrdersItems
AFTER DELETE,UPDATE
AS
BEGIN
SET NOCOUNT ON;
--Inerst the changed/deleted OrdersItems into the log
INSERT INTO dbo.logOrdersItems
SELECT * FROM DELETED
--Inserts the unchanged sibling OrdersItems records into the log
INSERT INTO dbo.logOrdersItems
SELECT oi.* FROM OrdersItems oi
WHERE oi.OrderId IN (SELECT DISTINCT OrderId FROM DELETED)
AND oi.OrderItemsID NOT IN (SELECT DISTINCT OrderItemsID FROM DELETED);
INSERT INTO dbo.logOrders
SELECT o.* FROM Orders o
WHERE o.OrderID IN (SELECT DISTINCT OrderId FROM DELETED);
END
GO
The Orders Trigger is fairly straightforward. Use the virtual DELETED table to insert the original version of the records into the log. Then join to the child OrdersItems records and insert them into the log as well. The way this is written, it will work even if you update or delete multiple Order records at a time.
The OrdersItems Trigger is a bit more complicated. You need to log the pre-chage version of the OrdersItems and Orders Records. But you also want (I think) to log the unchanged "sibling" OrdersItems records as well so that you have a complete picture of the records.
I know this is just your sample data, but you will want to add some kind of a timestamp to the records in the log tables. Otherwise you just end up with a bunch of duplicate rows and you cannot tell which is which. At the beginning of the trigger you can create a variable to hold the update datetime and then append that to your INSERT statement for the logs.
DECLARE #UpdateDateTime DATETIME;
SET #UpdateDateTime = GETUTCDATE();
I have stored procedures that inserts/updates records in some tables. Some columns of those tables have default values or auto-increment. Here's what I have:
ALTER PROCEDURE [dbo].[Usp___NewExpense]
#iCampaignID int,
#iCategory int,
#iUserID int,
#dDate Date,
#iAmountInINR int,
#strComments VarChar(200)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO dbo.Tbl_Expenses(iCampaignID, iCategory, dDate, iAmountInINR, strComments)
VALUES (#iCampaignID, #iCategory, #dDate, #iAmountInINR, #strComments);
-- How to get the record inserted using the above statement here without using triggers
-- or another select statement, so that I can assign values to the following variables?
Declare #justInsertedValue1 type1;
Declare #justInsertedValue2 type2;
Declare #justInsertedValue3 type3;
INSERT INTO dbo.Tbl_SomeOtherTable(col1, col2, col3)
VALUES (justInsertedValue1, justInsertedValue2, justInsertedValue3);
END
GO
Tbl_Expenses has about 9 columns in which two have default values and two have auto-increment set. How can I get the just inserted record just below my INSERT statement?
I know that I can use SCOPE_IDENTITY() and then a SELECT, but a query would probably make it inefficient (am I right?).
(By getting the just inserted record, I mean values of all fields of the just inserted record)
Edit: I haven't specified values for all the fields in my INSERT statement. I want to get those values inserted automatically by SQL Server due to DEFAULT/AUTO INCREMENT constraints also.
You can use the OUTPUT clause. You can even combine both inserts into one composite:
create table T1 (ID int IDENTITY(1,1) not null,ColA varchar(10) not null)
create table T2 (ID int IDENTITY(1,1) not null,T1ID int not null,ColB varchar(10) not null)
--Look ma! no local variables at all
insert into T2 (T1ID,ColB)
select t1.ID,'def'
from (
insert into T1(ColA)
output inserted.ID
values ('abc')
) t1
select * from T1
select * from T2
Results:
ID ColA
----------- ----------
1 abc
ID T1ID ColB
----------- ----------- ----------
1 1 def
I need to do the following to calculate customer reviews and show them on the page:
STEP 1.
Select data from T1 , count records and calculate the rating
SELECT COUNT(Rating) As ReviewCount,
ObjectID as ObID,
SUM(Rating)/COUNT(Rating) As ReviewScore
FROM [dbo].[Comment]
WHERE ObjectTypeID ='2' AND StatusID ='2'
GROUP BY ObjectID
This code works fine.
Next I want t do is insert calculated ReviewScore value into T2
INSERT INTO [dbo].[AttributeValue] (AttributeID, Value, SortOrder)
VALUES (5,ReviewScore, 29)
STEP 2
Next I want to do is get Identity (Last inserted ID) per each item for example:
DECLARE #ID INT= ##IDENTITY
STEP3
I want to get the ##Identity per inserted row in STEP 2 and Insert new data:
------- AtribbuteID is always 5
---- ObID is taken from the STEP 1
INSERT INTO [dbo].[AttributeObjectValue]
([AttributeID],[ObjectID],[Value],[AttributeValueID])
VALUES (5,ObID,ReviewScore,#ID)
I am trying to use the CTE table but cant get it to work:
BEGIN TRAN
GO
;WITH CTE (ReviewCount, ObjectID, ReviewScore)
AS
(
SELECT COUNT(Rating) As ReviewCount,
ObjectID as ObID,
SUM(Rating)/COUNT(Rating) As ReviewScore
FROM [dbo].[Comment]
WHERE ObjectTypeID ='2' AND StatusID ='2'
GROUP BY ObjectID
)
INSERT INTO [dbo].[AttributeValue] (AttributeID, Value, SortOrder)
VALUES (5,ReviewScore, 29)
SELECT ReviewCount FROM CTE
DECLARE #ID INT= ##IDENTITY
INSERT INTO [dbo].[AttributeObjectValue]
([AttributeID],[ObjectID],[Value],[AttributeValueID])
VALUES (5,ObID,ReviewCount,#ID)
GO
ROLLBACK TRAN
I will appreciate any help