sql Trigger: select the FK from another table before insert - sql

I have two database tables.
tblTeams: PK TeamID,TeamName
tblMatches: PK match id,FK HomeTeam,FK AwayTeam,Score.
I am using SQL Server 2008 and I am importing rows through the Wizard from a .csv file. The columns in the csv are hometeam,awayteam,score. Thus, before inserting in the tblMatches, I want a trigger that finds the FK of the team and inserts in the tblMatches the foreign key and not the name.
Any help with that please.
CREATE TRIGGER tblmatches_BeforeInsert
ON tblmatches
BEFORE INSERT
AS
BEGIN
INSERT tblmatches
SELECT teamName
FROM tblmatches
WHERE tblTeams.id = ?i dont know here what to insert?
END

If you want a different representation in the table then you'll probably have to implement a view, and perform the inserts via it, rather than the base table.
Something like:
CREATE TABLE realMatches (
MatchID int IDENTITY(1,1) not null, /* Identity? */
HomeTeamID int not null,
AwayTeamID int not null,
Score int not null, /* int? */
constraint PK_realMatches PRIMARY KEY (MatchID),
constraint FK_Matches_HomeTeams (HomeTeamID) references tblTeams (TeamID),
constraint FK_Matches_AwayTeams (AwayTeamID) references tblTeams (TeamID)
)
GO
CREATE VIEW tblMatches
AS
SELECT
MatchID,
ht.TeamName as HomeTeam,
at.TeamName as AwayTeam,
Score
FROM
realMatches m
inner join
tblTeams ht
on
m.HomeTeamID = ht.TeamID
inner join
tblTeams at
on
m.AwayTeamID = at.TeamID
GO
CREATE TRIGGER T_Matches ON tblMatches
INSTEAD OF INSERT
AS
SET NOCOUNT ON
INSERT INTO realMatches (HomeTeamID,AwayTeamID,Score)
SELECT ht.TeamID,at.TeamID,i.Score
FROM
inserted i
inner join
tblTeam ht
on
i.HomeTeam = ht.TeamName
inner join
tblTeam at
on
i.AwayTeam = at.TeamName
You can now (assuming that "A Team" and "Team America" exist in tblTeams):
INSERT INTO tblMatches (HomeTeam,AwayTeam,Score)
VALUES ('A Team','Team America',19)
Of course, this doesn't (yet) deal with any updates which attempt to change a team in the matches table, nor what to do if a team doesn't yet exist in tblTeam, but you've not asked about those yet.

AFAIK, for a trigger to be called on tblMatches, you need to supply values for all the columns in that table and only for the columns in that table which means, you cannot pass a team name to a trigger so that it can be used to resolve the team ID.
If I were to do it, I would just create a table to insert the raw data as is, let the import wizard write records into this table, define a trigger on this table to insert records into the two derived tables viz. tblTeams, tblMatches. (SQL Server Triggers)
My attempt at writing one (didn't get a chance to verify as I don't have SQL server)
CREATE TRIGGER teams.process ON teams
AFTER INSERT
AS
BEGIN
DECLARE #homeTeamId INT
DECLARE #awayTeamId INT
DECLARE #maxTeamId INT
DECLARE #matchId INT
SELECT #maxTeamId = 0
SELECT #maxTeamId = ISNULL(MAX(teamId), 0) from tblTeams
--- Check if home team has already been inserted into the table.
SELECT #homeTeamId = -1
SELECT
#homeTeamId = teamId
FROM
tblTeams t
JOIN inserted i
ON t.teamName = i.hometeam
IF (#homeTeamId = -1)
BEGIN
SELECT #homeTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #homeTeamId, i.hometeam FROM inserted i
END
--- Check if away team has already been inserted into the table.
SELECT #awayTeamId = -1
SELECT
#awayTeamId = teamId
FROM
tblTeams t
JOIN inserted i
ON t.teamName = i.awayteam
IF (#awayTeamId = -1)
BEGIN
SELECT #awayTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #awayTeamId, i.awayteam FROM inserted i
END
-- insert a record into the matches table with the home team ID and away team ID.
SELECT #matchId = 0
SELECT #matchId = ISNULL(MAX(MatchId), 0) FROM tblMatches
INSERT INTO tblMatches
SELECT #matchId + 1, #homeTeamId, #awayTeamId, i.score
FROM inserted i
END

Related

Trigger to update balance after a transaction amount record has been changed

Tables account and transactions
Account = {accNumber, balance, ...}
Transaction = {accNumber, amount, transNumber, ...}
Where Transaction.accNumber references Account.accNumber
I have managed to create trigger to update balance after INSERT
CREATE TRIGGER TR_Account_Balance
ON Transactions AFTER INSERT
AS
BEGIN
UPDATE account SET
balance = ins.newBalance
FROM (
SELECT a.accnumber,a.balance + SUM(i.amount) AS newBalance
FROM Account a
INNER JOIN inserted i ON i.accNumber = a.accNumber
GROUP BY a.accNumber, a.balance
) AS ins
WHERE account.accnumber = ins.accnumber
END
Now I need to create a trigger that would change balance accordingly to transaction AFTER UPDATE.
Example:
|accNumber | balance | ...
|-----------------------------
| 1 | 100 | ...
|accNumber | amount | ...
|-----------------------------
| 1 | 20 | ...
If we UPDATE amount to 10, balance should change to 90.
How can I possibly do that?
You should really do this in a normalized fashion, by using a view. For better performance, you can index it.
Indexed views are subject to some restrictions, in particular:
No outer joins or applys
Must be schema-bound
Grouped views need COUNT_BIG and can only use SUM as another aggregate
CREATE VIEW dbo.vAccountBalance
WITH SCHEMABINDING AS
SELECT
tr.accnumber,
SUM(tr.amount) AS balance,
COUNT_BIG(*) AS numTransactions -- this MUST be added
FROM dbo.Transactions tr; -- schema-qualify
GO
CREATE UNIQUE CLUSTERED INDEX CX_vAccountBalance ON dbo.vAccountBalance (accnumber);
The server will maintain this index together with other indexes, during any insert, update or delete.
If you really wanted to do this in a trigger, you can use the following
Note how the Account table is only referenced once, and the difference is added, rather than self-joining again
Note how inserted and deleted are joined together by primary key, and the difference is summed
CREATE TRIGGER TR_Account_Balance
ON Transactions AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted) AND NOT EXISTS (SELECT 1 FROM deleted)
RETURN; -- early bail-out
UPDATE a -- update the already referenced Account table
SET
balance += ins.diffBalance
FROM Account a
INNER JOIN (
SELECT
i.accnumber,
SUM(i.amount) AS diffBalance
FROM (
SELECT i.transNumber, i.accnumber, i.amount
FROM inserted i
)
FULL JOIN (
SELECT d.transNumber, d.accnumber, -(d.amount)
FROM deleted d
) ON i.transNumber = a.transNumber
GROUP BY i.accNumber
) AS ins ON a.accnumber = ins.accnumber;
GO
You could also split this up into separate INSERT UPDATE and DELETE triggers, in which case you can remove the deleted section for the former, remove the inserted section for the latter, and change the UPDATE one to use an INNER JOIN instead of a FULL JOIN.
If you do the insert update delete via a proc that will be the best place to update the mapped table or other tables as well.
If you still want to do it in a trigger (Carefully) please compute your SUM at same table level and update the balance on main table so it'll cover update and delete as well.
Schema:
DROP TABLE IF EXISTS dbo.AccountTransaction
DROP TABLE IF EXISTS dbo.Account
CREATE TABLE dbo.Account
(
AccountNumber INT CONSTRAINT PK_AccountId PRIMARY KEY CLUSTERED IDENTITY(1, 1) NOT NULL,
Balance DECIMAL(18, 9) CONSTRAINT DF_Account_Balance DEFAULT 0.0 NOT NULL
)
GO
INSERT INTO dbo.Account
(
Balance
)
VALUES
(
DEFAULT -- decimal(18, 9)
)
CREATE TABLE dbo.AccountTransaction
(
AccountTransactionId INT CONSTRAINT PK_AccountTransactionId PRIMARY KEY CLUSTERED IDENTITY(1, 1) NOT NULL,
AccountNumber INT CONSTRAINT FK_AccountTransaction_Account FOREIGN KEY REFERENCES dbo.Account (AccountNumber) NOT NULL,
Amount DECIMAL(18, 9) CONSTRAINT DF_AccountTransaction_Amount DEFAULT 0.0 NOT NULL
)
GO
CREATE TRIGGER dbo.tr_AccountTransaction
ON dbo.AccountTransaction
FOR INSERT, UPDATE, DELETE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Inserted AS INT =
(
SELECT COUNT (1)
FROM INSERTED
)
DECLARE #Deleted AS INT =
(
SELECT COUNT (1)
FROM DELETED
)
IF #Inserted > 0
BEGIN
UPDATE dbo.Account
SET Balance = x.NewBalance
FROM
(
SELECT SUM (at.Amount) AS NewBalance
FROM Inserted AS i
JOIN dbo.AccountTransaction AS at
ON at.AccountNumber = i.AccountNumber
GROUP BY i.AccountNumber
) AS x
END
IF #Inserted = 0
AND #Deleted > 0
BEGIN
UPDATE dbo.Account
SET Balance = x.NewBalance
FROM
(
SELECT SUM (at.Amount) AS NewBalance
FROM Deleted AS d
JOIN dbo.AccountTransaction AS at
ON at.AccountNumber = d.AccountNumber
GROUP BY d.AccountNumber
) AS x
END
END
GO
** DEBUG**
INSERT INTO dbo.AccountTransaction
(
AccountNumber,
Amount
)
SELECT a.AccountNumber,
12.0
FROM dbo.Account AS a
SELECT a.AccountNumber,
a.Balance
FROM dbo.Account AS a
UPDATE at
SET at.Amount += 30
FROM dbo.AccountTransaction AS at
WHERE at.AccountTransactionId = 1
SELECT a.AccountNumber,
a.Balance
FROM dbo.Account AS a
SELECT at.AccountTransactionId,
at.AccountNumber,
at.Amount
FROM dbo.AccountTransaction AS at
UPDATE at
SET at.Amount -= 20
FROM dbo.AccountTransaction AS at
WHERE at.AccountTransactionId = 1
SELECT a.AccountNumber,
a.Balance
FROM dbo.Account AS a
SELECT at.AccountTransactionId,
at.AccountNumber,
at.Amount
FROM dbo.AccountTransaction AS at
DELETE a
FROM dbo.AccountTransaction AS a
WHERE a.AccountTransactionId = 2
SELECT a.AccountNumber,
a.Balance
FROM dbo.Account AS a
SELECT at.AccountTransactionId,
at.AccountNumber,
at.Amount
FROM dbo.AccountTransaction AS at

Insert all values from a table's column to another table's column in Sql

I have two tables Roles and Menus and there is a relation on MenuId between these two tables. Both tables has relationship column with the same name "MenuId".
Menus has Primary Key and Roles has Foreign Key columns correspondingly.
I want to insert MenuId from Menus table to Roles Table using a loop, the Roles tables should have all the MenuId(s) from Menus table.
Something like as shown in below image.
RoleID 1 then all MenuID, then RoleId 2 and again all MenuID.
But I do not want insertion using triggers.
I have tried something like :-
DECLARE #counter int
SET #counter = 0
WHILE #counter < 65 BEGIN
UPDATE Roles SET MenuId = #counter + 1
SET #counter = #counter + 1
END
create a 3rd table with the required columns and execute the below query on that table
insert into table3 (select table1.r_id,table2.menu_id from table1 cross join table2);
To update existing RoleIds, you can use your method slightly modified:
DECLARE #counter int =0
DECLARE #records int
SELECT #records = COUNT(MenuId) FROM Menus
WHILE #counter < #records
BEGIN
UPDATE Roles SET MenuId = #counter + 1
WHERE RoleId = 1
SET #counter = #counter + 1
END
After that, if you want to insert each MenuId against every RoleId:
you can use "INSERT INTO ... SELECT ..." statement as,
DECLARE #roles int = 0
WHILE #roles < 10 --assuming that you have **10 roles** to insert
BEGIN
INSERT INTO Roles(MenuId, RoleId)
SELECT MenuId, #roles --it's a roleId you want to insert
FROM Menus m
SET #roles = #roles + 1
END
Above query will insert all MenuId against every RoleId
The elephant in the room is doing things in a loop when working with SQL - performance is generally terrible and you almost never need to.
Not entirely clear on your db structure, but this should point you in the right direction:
create table Menu
(
MenuId int
);
create table Role
(
RoleId int
);
create table RoleMenu
(
RoleId int,
MenuId int
);
insert into Menu(MenuId) values(1),(2),(3);
insert into Role(RoleId) values(1),(2),(3),(4);
-- some data already in table
insert into RoleMenu(RoleId, MenuId) values(1,1), (1,2);
with cte as (
select distinct RoleId, MenuId
from Menu
cross join Role
)
insert into RoleMenu(RoleId, MenuId)
select cte.RoleId, cte.MenuId
from cte
left outer join RoleMenu rm on cte.MenuId = rm.MenuId and cte.RoleId = rm.RoleId
where rm.RoleId is null -- don't insert where we already have data
select * from RoleMenu order by RoleId, MenuId

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

Trigger After Update SQL

I have Customer table. To simplify lets say i have two columns
Id
Name
I have a second table (Log) that I want to update ONLY when the Id column of my customer changes. Yes you heard me right that the primary key (Id) will change!
I took a stab but the NewId that gets pulled is the first record in the Customer table not the updated record
ALTER TRIGGER [dbo].[tr_ID_Modified]
ON [dbo].[customer]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE (Id)
BEGIN
UPDATE [log]
SET NewId = Id
FROM customer
END
END
Many would make the argument that if you are changing PK values, you need to rethink the database/table design. However, if you need a quick & dirty fix, add a column to the customer table that is unique (and not null). Use this column to join between the [inserted] and [deleted] tables in your update trigger. Here's a sample script:
CREATE TABLE dbo.Customer (
Id INT CONSTRAINT PK_Customer PRIMARY KEY,
Name VARCHAR(128),
UQColumn INT IDENTITY NOT NULL CONSTRAINT UQ_Customer_UQColumn UNIQUE
)
CREATE TABLE dbo.[Log] (
CustomerId INT NOT NULL,
LogMsg VARCHAR(MAX)
)
INSERT INTO dbo.Customer
(Id, Name)
VALUES
(1, 'Larry'),
(2, 'Curley'),
(3, 'Moe')
INSERT INTO dbo.[Log]
(CustomerId, LogMsg)
VALUES
(1, 'Larry is cool'),
(1, 'Larry rocks'),
(2, 'Curley cracks me up'),
(3, 'Moe is mean')
CREATE TRIGGER [dbo].[tr_Customer_Upd]
ON [dbo].[customer]
FOR UPDATE
AS
BEGIN
UPDATE l
SET CustomerId = i.Id
FROM inserted i
JOIN deleted d
ON i.UQColumn = d.UQColumn
JOIN [Log] l
ON l.CustomerId = d.Id
END
SELECT *
FROM dbo.[Log]
UPDATE dbo.Customer
SET Id = 4
WHERE Id = 1
SELECT *
FROM dbo.[Log]

Create trigger prevent insert

I'm trying to execute the following trigger:
create trigger t23
on studies
after insert, update, delete
as
begin
REFERENCING NEW ROW NewStudent
FOR EACH ROW
WHEN (30 <= (SELECT SUM(credits) FROM Studies)
DELETE FROM NewStudent N
WHERE N.spnr = NewStudent.spnr
end
I'm trying to create a trigger which only inserts a student if the credits is < or == to '30'. The "Credits" is a type int.
I'm getting numerous errors trying to implement this trigger. I really have tried everything and i m out of options. Could someone who is expert in the field point me in the right direction?
The example "Using a DML AFTER trigger to enforce a business rule between the PurchaseOrderHeader and Vendor tables" in the CREATE TRIGGER MSDN documentation does exaclty what you're looking for:
USE AdventureWorks2008R2;
GO
IF OBJECT_ID ('Purchasing.LowCredit','TR') IS NOT NULL
DROP TRIGGER Purchasing.LowCredit;
GO
-- This trigger prevents a row from being inserted in the Purchasing.PurchaseOrderHeader table
-- when the credit rating of the specified vendor is set to 5 (below average).
CREATE TRIGGER Purchasing.LowCredit ON Purchasing.PurchaseOrderHeader
AFTER INSERT
AS
DECLARE #creditrating tinyint, #vendorid int;
IF EXISTS (SELECT *
FROM Purchasing.PurchaseOrderHeader p
JOIN inserted AS i
ON p.PurchaseOrderID = i.PurchaseOrderID
JOIN Purchasing.Vendor AS v
ON v.BusinessEntityID = p.VendorID
WHERE v.CreditRating = 5
)
BEGIN
RAISERROR ('This vendor''s credit rating is too low to accept new purchase orders.', 16, 1);
ROLLBACK TRANSACTION;
RETURN
END;
The key here is ROLLBACK TRANSACTION, just adapt the example to suit your need and you're done.
Edit: This should accomplish what you're looking for, but I have not tested it so your mileage may vary.
create trigger dbo.something after insert as
begin
if exists ( select * from inserted where sum(credits) > 30 )
begin
rollback transaction
raiserror ('some message', 16, 1)
end
end
Another edit, based on some assumptions (please note I wrote this script on the fly since I can't test it right now):
create table dbo.students
(
student_id int not null,
name varchar (50) not null
)
create table dbo.courses
(
course_id int not null,
name varchar (50) not null,
required_credits int not null
)
create table dbo.results
(
student_id int not null,
course_id int not null,
course_result int not null
)
create trigger dbo.check_student_results on dbo.results after insert as
(
declare #check int
select #check = count(*)
from inserted as a
join dbo.courses as b on b.course_id = a.course_id
where b.required_credits > a.course.result
if #check <> 0
begin
rollback transaction
raiserror('The student did not pass the course.', 16, 1)
end
)
This way when you insert records in the dbo.results table the constraint checks if the student has passed the course, and cancels the insertion if appropriate. However, it's better to check this things in the application layer.