I am trying to create an 'instead of insert trigger' that will not let the name 'john' insert anything into a table. My problem is that even if i change the name to something else, the query is successful but the values arent added.
Any help would be appreciated, thanks in advance.
CREATE TRIGGER InsteadOfTrigger
ON Question4
INSTEAD OF INSERT
AS
Declare #name varchar(50)
Declare #question varchar(50)
Declare #Answer char
Set #name = 'John'
IF (select Username from inserted) = #name
BEGIN
RAISERROR ('You have not paid up your fee', 10,1)
ROLLBACK TRANSACTION
END
ELSE
BEGIN
INSERT INTO question4
values (#name, #question, #Answer)
END
Ok So I have removed your BEGIN and END statements between your IF ELSE statement and wrapped the trigger logic within a BEGIN END
As mentioned in the comments below you dont need the ROLLBACK TRANSACTION
Also you will need to populate #question and #Answer for those to be of any use.
CREATE TRIGGER InsteadOfTrigger
ON Question4
INSTEAD OF INSERT
AS
BEGIN
Declare #name varchar(50)
Declare #question varchar(50)
Declare #Answer char
Set #name = 'John'
IF (select Username from inserted) = #name
RAISERROR ('You have not paid up your fee', 10,1)
--ROLLBACK TRANSACTION
ELSE
INSERT INTO question4
values (#name, #question, #Answer)
END
Hmm, I notice you have declared, but not actually set a value for your variables in your else statement this may have caused SQL to not insert what you expected.
Strangely enough I'm required to do the same in an assignment at the moment, Here's my solution:
CREATE TRIGGER instead_of_insert
ON Question4
INSTEAD OF INSERT AS
Declare #Username varchar(25)
Declare #Question varchar(6)
Declare #Answer char(1)
Set #Username ='John'
IF (Select UserName from inserted) = #UserName
Begin
RAISERROR ('You have not paid up your fee', 10,1)
End
Else
Begin
Set #Username = (Select UserName from inserted)
Set #Question = (Select Question_ID from inserted)
Set #Answer = (Select Answer from inserted)
Insert into User_Responses
Values
(#username, #Question, #Answer)
End
Related
alter procedure product_sales
#productid int,
#quantitysell int
as
begin
declare #productname varchar(20)
declare #quantityavailable int
select #quantityavailable=quantityav from products_trycatch
select #productname=productname from products_trycatch where productid=#productid
select #productid=productid from products_trycatch
if(not exists(select #productid from products_trycatch)
begin
raiserror('Product does not exist',16,1)
end
else
begin
if (#quantitysell>#quantityavailable)
begin
print 'Stock not available'
end
else
begin
-------------
update products_trycatch set quantityav=quantityav-#quantitysell
insert into product_log values(#productid,#productname,#quantitysell)
end
Please let me know where the mistake is. What i am trying to do is. one table contains stock available for a product, when i execute the SP i mentioned which product and how many quantity is being sold, The sp deducts that value from the available quantity table and updates in a new table the quantity sold.
You're thinking very procedurally, laying things out step by step, but missing parts out from several of your steps.
Don't write several queries to retrieve individual pieces of data. Think about the problem as a whole1:
alter procedure product_sales
#productid int,
#quantitysell int
as
begin
declare #rc int
update products_trycatch
set quantityav = quantityav - #quantitysell
where productid = #productid and quantityav > #quantitysell
set #rc = ##ROWCOUNT
if #rc = 1
begin
insert into product_log
select #productid,productname,#quantitysell
from product_trycatch
where productid = #productid
end
else
begin
if not exists(select * from products_trycatch where productid = #productid)
begin
raiserror('Product does not exist',16,1)
end
else
begin
print 'Stock not available'
end
end
Not how all of my queries target the row in product_trycatch with the matching productid column - several of yours don't which means that they're going to be assigning non-deterministic values to your variables, or updating all rows in product_trycatch and deducting the #quantitysell value.
1For bonus points we could write a single update with case and an output clause that would eliminate the need to perform any re-querying of the product_trycatch table for the product name or in the failure path, but it's probably not worth the additional complexity here. This query shows the general technique:
declare #products table (ID int not null, Quantity int not null, Name varchar(20) not null)
insert into #products (ID,Quantity,Name) values (1,15,'Fred')
declare #ID int
declare #Qty int
declare #RefData table (OldQuantity int not null, NewQuantity int not null,
Name varchar(20) not null)
select #ID = 1, #Qty = 20
update #products
set Quantity = CASE WHEN Quantity >= #Qty THEN Quantity - #Qty ELSE Quantity END
output deleted.Quantity,inserted.Quantity, inserted.Name into #RefData
where ID = #ID
select * from #RefData
where you can play with the #ID and #Qty values to see the various outcomes reflected in #RefData when the quantity requested is higher than that which is available or where the product does or doesn't exist.
Formatted your code and added missing words -
alter procedure product_sales
#productid int,
#quantitysell int
as
begin
declare #productname varchar(20)
declare #quantityavailable int
select #quantityavailable=quantityav from products_trycatch
select #productname=productname from products_trycatch where productid=#productid
select #productid=productid from products_trycatch
if not exists(select #productid from products_trycatch)
begin
raiserror('Product does not exist',16,1)
end
else if (#quantitysell>#quantityavailable)
begin
print 'Stock not available'
end
else
begin
-------------
update products_trycatch set quantityav=quantityav-#quantitysell
insert into product_log values(#productid,#productname,#quantitysell)
end
end
Here is the Formatted code
alter procedure product_sales
#productid int,
#quantitysell int
as
begin
declare #productname varchar(20)
declare #quantityavailable int
select #quantityavailable=quantityav from products_trycatch
select #productname=productname from products_trycatch where productid=#productid
select #productid=productid from products_trycatch
if(not exists(select #productid from products_trycatch))
begin
raiserror('Product does not exist',16,1)
end
else if (#quantitysell>#quantityavailable)
begin
print 'Stock not available'
end
else
begin
-------------
update products_trycatch set quantityav=quantityav-#quantitysell
insert into product_log values(#productid,#productname,#quantitysell)
end
end
Just Modified your Stored Proc have a look at it
ALTER PROCEDURE Product_sales
(#Productid INT,
#Quantitysell INT
)
AS
BEGIN TRY
DECLARE #Productname VARCHAR(20)
DECLARE #Quantityavailable INT
SELECT #Quantityavailable = Quantityav
FROM Products_trycatch
SELECT #Productname = Productname
FROM Products_trycatch
WHERE Productid = #Productid
SELECT #Productid = Productid
FROM Products_trycatch
IF( #Productid IS NULL )
BEGIN
RAISERROR('Product does not exist',16,1)
END
ELSE IF ( #Quantitysell > #Quantityavailable )
BEGIN
PRINT 'Stock not available'
END
ELSE
BEGIN
DECLARE #Is_transcount INT
BEGIN TRANSACTION
SET #Is_transcount=1
UPDATE Products_trycatch
SET Quantityav = Quantityav - #Quantitysell;
INSERT INTO Product_log
VALUES (#Productid,
#Productname,
#Quantitysell)
COMMIT TRANSACTION
SET #Is_transcount=0
END
END TRY
BEGIN CATCH
IF( ##Trancount > 0 )
ROLLBACK TRANSACTION
DECLARE #Error_message VARCHAR(Max),
#Error_number INT,
#Error_procedure VARCHAR(100)
SELECT #Error_message = ERROR_MESSAGE(),
#Error_number = ERROR_NUMBER(),
#Error_procedure = ERROR_PROCEDURE()
END CATCH
The SP is open to a Parameter Sniffing issue.
You re-assign the value of #productid part way through your code.
From this point forward SQL will be making more assumptions about what plan to use because it no longer knows the actual value.
I am writing a procedure in SQL Server to insert or update records.
The update part of the code is working fine but when I am executing it for inserting, duplicate entries are inserted into the table.
I created the primary key to avoid this error but after creating that I am not able to insert any single record.
Here is the code :
Alter Procedure test_case
#id int,
#name nvarchar(20)
AS
If exists (Select t_id from testing2 where t_id = #id)
begin
update testing2
set t_id = #id, t_name = #name
where t_id = #id
end
else
begin
insert into testing2 (t_id, t_name, last_date, hard)
select
#id, #name, convert(date, getdate()), 'null'
from test
end
On executing it is showing 2 rows affected
You do not require test table in the select query
insert into testing2 (t_id, t_name, last_date, hard)
select
#id as t_id, #name as t_name, convert(date, getdate()) as last_date, 'null' as hard
is enough
I like to break functionality into smaller parts because it helps me to manage code better.
Maybe this is not a good example since it is pretty simple but I will write it anyway.
Create Procedure Testing2_InsertData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
Insert Into testing2
(t_id, t_name, last_date, hard)
Values
( #id, #name, GetDate(), null )
Go
Create Procedure Testing2_UpdateData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
Update testing2 Set
t_name = #name --, maybe last_date = GetDate()
Where ( t_id = #id )
Go
Create Procedure Testing2_SaveData (
#id int,
#name nvarchar(20)
) As
Set NoCount On
If ( Exists( Select t_id From testing2 Where ( t_id = #id ) ) )
Exec Testing2_UpdateData #id, #name
Else
Exec Testing2_InsertData #id, #name
Go
Dear all I´m having trouble with my trigger.
Am I doing this at all right, right now it only works for Insert. I think I´m pretty close tho please help me if you have the time. I´m trying to store all the inserts, updates and deletes into the table customers_changelog via trigger. There is something wrong with the code I cant delete or update customers I can only insert new ones. Please help my I have been spending plenty of hours on this and just cant get this to work! :)
create table customers (
customerid int identity primary key,
name varchar(100) not null,
address varchar(100)
)
go
create table customers_changelog (
customerid int,
name varchar(100) not null,
address varchar(100),
change_user varchar(32),
change_time datetime,
change_action char(1) default 'I',
check (change_action = 'I' or change_action = 'D')
)
go
CREATE TRIGGER log_changes
ON customers
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
--
-- Check if this is an INSERT, UPDATE or DELETE Action.
--
DECLARE #customerid1 as int;
DEClARE #name1 as varchar(32);
DECLARE #address1 as varchar(100);
DECLARE #change_action1 as char(1);
DECLARE #change_time1 as datetime;
DECLARE #change_user1 as varchar(32);
select #customerid1 = c.customerid, #name1 = c.name, #address1 = c.address
from customers c, inserted i
where c.customerid = i.customerid
SET #change_time1 = CURRENT_TIMESTAMP;
SET #change_user1 = CURRENT_USER;
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'I',#change_time1,#change_user1)
IF EXISTS(SELECT * FROM DELETED)
BEGIN
IF EXISTS(SELECT * FROM INSERTED)
INSERT INTO customers_changelog VALUES(#customerid1,#name1,#address1,'U',#change_time1,#change_user1)
ELSE
INSERT INTO customers_changelog VALUES(#customerid1,#name1,#address1,'D',#change_time1,#change_user1)
END
ELSE
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN;
END
Assuming MS-SQL from syntax - So couple issues here:
1. Need to specify column lists in the "update" and "delete" inserts because the column order in the table doesn't match your inserts.
2. Can't use "inserted" data for delete insert
ALTER TRIGGER [dbo].[log_changes] ON [dbo].[customers] AFTER INSERT, UPDATE, DELETE AS
BEGIN
SET NOCOUNT ON;
DECLARE #customerid1 as int;
DEClARE #name1 as varchar(32);
DECLARE #address1 as varchar(100);
DECLARE #change_action1 as char(1);
DECLARE #change_time1 as datetime;
DECLARE #change_user1 as varchar(32);
select #customerid1 = c.customerid, #name1 = c.name, #address1 = c.address
from customers c, inserted i
where c.customerid = i.customerid
SET #change_time1 = CURRENT_TIMESTAMP;
SET #change_user1 = CURRENT_USER;
IF EXISTS(SELECT * FROM DELETED)
BEGIN
IF EXISTS(SELECT * FROM INSERTED)
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'U',#change_time1,#change_user1)
ELSE
BEGIN
select #customerid1 = d.customerid, #name1 = d.name, #address1 = d.address
from deleted d
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'D',#change_time1,#change_user1)
END
END
ELSE
BEGIN
IF NOT EXISTS(SELECT * FROM INSERTED) RETURN;
INSERT INTO customers_changelog(customerid,name,address,change_action,change_time,change_user)
VALUES(#customerid1,#name1,#address1,'I',#change_time1,#change_user1)
END
END
I have created a stored procedure to retrieve some details based on the certain values passed to a parameter. THis requires switching between the SQLs to be executed by stored procedure. Following is the code:
USE [DFS]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
end
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
End
end
END
The entire processing is based on the variable #userType. Not sure why the stored procedure is not compiling.
Formatting is your friend, just with a quick glance, it appears you have too many ENDs -- See SQL Fiddle with working Demo:
CREATE PROCEDURE [dbo].[DAFS]
#EmailID Nvarchar(128),
#clientID int,
#userType Varchar(50),
#Success numeric output,
#msg varchar(100) output
AS
BEGIN
if #userType='Normal User'
IF EXISTS (SELECT 1 FROM dbo.Allcdn
WHERE EmailID = #EmailID AND ClientID = #clientID)
begin
set #Success=0
set #msg='Carry on ....'
end
else
begin
set #Success=6
set #msg='Not allowed ...'
END
else
Begin
IF EXISTS (SELECT 1 FROM dbo.Alcon
WHERE EmailID = #EmailID AND ClientID = #clientID)
BEGIN
set #Success=0
set #msg='Carry on...'
END
END
end
I have two tables User & User Log . User log table basically logs all the changes(insert/update/delete) made to user table.
I have a trigger on User table which is as below:
ALTER TRIGGER [dbo].[TRG_UserLog]
ON [dbo].[Users]
FOR INSERT,UPDATE,DELETE
AS
-- Declare variables here
DECLARE #UserName VARCHAR(50)
DECLARE #FirstName VARCHAR(50)
DECLARE #LastName VARCHAR(50)
DECLARE #Email VARCHAR(50)
DECLARE #RoleID INT
DECLARE #UpdatedBy VARCHAR(50)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
IF ##ROWCOUNT = 0
BEGIN
RETURN
END
IF EXISTS(SELECT * FROM INSERTED)
--INSERTED / UPDATED
BEGIN
SET #UserName = ( SELECT UserName FROM INSERTED)
SET #FirstName = ( SELECT FirstName FROM INSERTED)
SET #LastName = ( SELECT LastName FROM INSERTED)
SET #Email = ( SELECT Email FROM INSERTED)
SET #RoleID = ( SELECT RoleID FROM INSERTED)
SET #UpdatedBy = ( SELECT ModifiedBy FROM INSERTED)
INSERT INTO UserLog(UserName,FirstName,LastName,Email,RoleID,[DateTime],UpdatedBy)
VALUES (#UserName,#FirstName,#LastName,#Email,#RoleID,GETDATE(),#UpdatedBy)
END
ELSE
-- DELETED
BEGIN
SET #UserName = ( SELECT UserName FROM DELETED)
SET #FirstName = ( SELECT FirstName FROM DELETED)
SET #LastName = ( SELECT LastName FROM DELETED)
SET #Email = ( SELECT Email FROM DELETED)
SET #RoleID = ( SELECT RoleID FROM DELETED)
SET #UpdatedBy = ( SELECT ModifiedBy FROM DELETED)
INSERT INTO UserLog(UserName,FirstName,LastName,Email,RoleID,[DateTime],UpdatedBy)
VALUES (#UserName,#FirstName,#LastName,#Email,#RoleID,GETDATE(),#UpdatedBy)
END
END
The above triigger is not inserting data in userlog table when insert/update or delete is made to user table. Is there anything wrong with the code?
You should not be setting variables from INSERTED and DELETED. These "tables" could potentially hold more than 1 row in them and using set is going to lose data. Do this instead (on both the INSERT and DELETE blocks):
INSERT INTO UserLog(UserName, FirstName, LastName, Email, RoleID, [DateTime], UpdatedBy)
SELECT UserName, FirstName, LastName, Email, RoleID, getdate(), ModifiedBy
FROM INSERTED
If you make that change, you don't even need the IF/ELSE blocks, since it'll only INSERT/DELETE based on whether or not there are rows in those tables.
Also, the check on ##ROWCOUNT is unnecessary. You should be able to remove that completely.
This will always be true:
SET NOCOUNT ON; -- this sets ##ROWCOUNT to 0
IF ##ROWCOUNT = 0
BEGIN
RETURN
END
because calling SET NOCOUNT ON; affects ##ROWCOUNT, and since no rows are affected by that statement, it's set to 0. So the rest of the code never runs. At the very least, you would run that code before SET NOCOUNT ON; (or store ##ROWCOUNT in a variable for later use), but as indicated by the other answer, it's completely unnecessary anyway.