SQL Server trigger on Insert and Update - sql-server

I am looking to create a SQL Server trigger that moves a record from one table to an identical replica table if the record matches a specific condition.
Questions: do I need to specify each column, or can I use a wildcard?
Can I use something like:
SET #RecID = (SELECT [RecoID] FROM Inserted)
IF NULLIF(#RecID, '') IS NOT NULL
(then insert....)
THANKS!

There's a lot of stuff you "CAN" do in a trigger, but that doesn't mean you should. I'd would urge to to avoid setting scalar variables within a trigger at all costs. Even if you 100% sure your table will never have more that 1 row inserted per transaction because that's how the app is designed... You'll be in for very rude awakening when you find out that not all transactions come through the application.
Below is a quick demonstration of both types of triggers...
USE tempdb;
GO
IF OBJECT_ID('tempdb.dbo.PrimaryTable', 'U') IS NOT NULL
DROP TABLE dbo.PrimaryTable;
GO
IF OBJECT_ID('tempdb.dbo.TriggerScalarLog', 'U') IS NOT NULL
DROP TABLE dbo.TriggerScalarLog;
GO
IF OBJECT_ID('tempdb.dbo.TriggerMultiRowLog', 'U') IS NOT NULL
DROP TABLE dbo.TriggerMultiRowLog;
GO
CREATE TABLE dbo.PrimaryTable (
Pt_ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY CLUSTERED,
Col_1 INT NULL,
Col_2 DATE NOT NULL
CONSTRAINT df_Col2 DEFAULT (GETDATE())
);
GO
CREATE TABLE dbo.TriggerScalarLog (
Pt_ID INT,
Col1_Old INT,
Col1_New INT,
Col2_Old DATE,
Col2_New DATE
);
GO
CREATE TABLE dbo.TriggerMultiRowLog (
Pt_ID INT,
Col1_Old INT,
Col1_New INT,
Col2_Old DATE,
Col2_New DATE
);
GO
--=======================================================
CREATE TRIGGER dbo.PrimaryCrudScalar ON dbo.PrimaryTable
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
DECLARE
#Pt_ID INT,
#Col1_Old INT,
#Col1_New INT,
#Col2_Old DATE,
#Col2_New DATE;
SELECT
#Pt_ID = ISNULL(i.Pt_ID, d.Pt_ID),
#Col1_Old = d.Col_1,
#Col1_New = i.Col_1,
#Col2_Old = d.Col_2,
#Col2_New = i.Col_2
FROM
Inserted i
FULL JOIN Deleted d
ON i.Pt_ID = d.Pt_ID;
INSERT dbo.TriggerScalarLog (Pt_ID, Col1_Old, Col1_New, Col2_Old, Col2_New)
VALUES (#Pt_ID, #Col1_Old, #Col1_New, #Col2_Old, #Col2_New);
GO -- DROP TRIGGER dbo.PrimaryCrudScalar;
CREATE TRIGGER PrimaryCrudMultiRow ON dbo.PrimaryTable
AFTER INSERT, UPDATE, DELETE
AS
SET NOCOUNT ON;
INSERT dbo.TriggerMultiRowLog (Pt_ID, Col1_Old, Col1_New, Col2_Old, Col2_New)
SELECT
ISNULL(i.Pt_ID, d.Pt_ID),
d.Col_1,
i.Col_1,
d.Col_2,
i.Col_2
FROM
Inserted i
FULL JOIN Deleted d
ON i.Pt_ID = d.Pt_ID;
GO -- DROP TRIGGER dbo.TriggerMultiRowLog;
--=======================================================
--=======================================================
-- --insert test...
INSERT dbo.PrimaryTable (Col_1)
SELECT TOP 100
o.object_id
FROM
sys.objects o;
SELECT 'INSERT Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'INSERT Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;
UPDATE pt SET
pt.Col_1 = pt.Col_1 + rv.RandomVal,
pt.Col_2 = DATEADD(DAY, rv.RandomVal, pt.Col_2)
FROM
dbo.PrimaryTable pt
CROSS APPLY ( VALUES (ABS(CHECKSUM(NEWID())) % 10000 + 1) ) rv (RandomVal);
SELECT 'UPDATE Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'UPDATE Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;
DELETE pt
FROM
dbo.PrimaryTable pt;
SELECT 'DELETE Scarar results';
SELECT * FROM dbo.TriggerScalarLog tsl;
SELECT 'DELETE Multi-Row results';
SELECT * FROM dbo.TriggerMultiRowLog tmrl;

You could, but I'd recommend against it. If your source table changed things would start failing.
Also, in your example if you were to ever have more than one row inserted at a time you would get thrown an error (or have unpredictable results). I'd recommend a more set based approach:
INSERT table2 ( user_id ,
user_name ,
RecoID
)
SELECT user_id ,
user_name ,
RecoID
FROM inserted i
LEFT JOIN table2 t ON i.RecoID = t.RecoID
WHERE t.RecoID IS NULL;
EDIT:
If you want to stop the insert happening on your original table then you'll need to do something along the lines of:
CREATE TRIGGER trigger_name
ON table_orig
INSTEAD OF INSERT
AS
BEGIN
-- make sure we aren't triggering from ourselves from another trigger
IF TRIGGER_NESTLEVEL() <= 1
return;
-- insert into the table_copy if the inserted row is already in table_orig (not null)
INSERT table_copy ( user_id ,
user_name ,
RecoID
)
SELECT user_id ,
user_name ,
RecoID
FROM inserted i
LEFT JOIN table_orig c ON i.RecoID = c.RecoID
WHERE t.RecoID IS NOT NULL;
-- insert into table_orig if the inserted row is not already in table_orig (null)
INSERT table_orig ( user_id ,
user_name ,
RecoID
)
SELECT user_id ,
user_name ,
RecoID
FROM inserted i
LEFT JOIN table_orig c ON i.RecoID = c.RecoID
WHERE t.RecoID IS NULL;
END;
The instead of will stop the insert if you don't want it to actually be inserted, so you'll need to do that yourself (the second insert statement).
Please note I changed some nulls to not nulls and the table we are left joining to in some cases.

Related

SQL Server : prevent change of field value when it was once != NULL

I want to create a trigger in SQL Server that prevents an update on a row if one specific field in that row already contains NON-NULL values.
It should then just ROLLBACK the update.
Background: if a onceChangedDate is set, it shall not be able to change it or NULL it again.
Table structure:
ID, UserName, Hidden, ChangedOneDate
Each entry will have normally at creation:
ID, SomeUser, 0, NULL
I have a trigger which will set ChangedOnceDate to the current date as soon the "Hidden" is set to 1.
And then I want to prevent any change on ChangedOnceDate for future.
How can I achieve this?
This is some what of a stab in the dark, but seems like an EXISTS where the value of the column in the deleted pseudo-table isn't NULL but is in the inserted pseudo-table is what you are after:
--Sample Table
CREATE TABLE dbo.YourTable (ID int IDENTITY(1,1),
SomeColumn varchar(10) NOT NULL,
NullableDate date NULL,
CONSTRAINT PK_YourTable PRIMARY KEY (ID));
GO
--Trigger solution
CREATE TRIGGER dbo.trg_NullableDateNulled_YourTable ON dbo.YourTable
AFTER UPDATE AS
BEGIN
IF EXISTS (SELECT 1
FROM inserted i
JOIN deleted d ON i.ID = d.ID
WHERE d.NullableDate IS NOT NULL
AND i.NullableDate IS NULL)
--Use an Error number relevant for your environment
THROW 78921,
N'A row where the column ''NullableDate'' has been set to NULL has been detected in the trigger ''trg_NullableDateNulled_YourTable''. Cannot update column ''NullableDate'' to be NULL when it previously had a non-NULL value in the object ''dbo.YourTable''.',
16;
END;
GO
You can then test (and clean up) with the following:
INSERT INTO dbo.YourTable (SomeColumn, NullableDate)
VALUES('asda',NULL),
('wera',GETDATE());
GO
--Following fails
UPDATE dbo.YourTable
SET NullableDate = NULL
WHERE SomeColumn = 'wera';
GO
--Following works
UPDATE dbo.YourTable
SET NullableDate = GETDATE()
WHERE SomeColumn = 'asda';
GO
--Following works
UPDATE dbo.YourTable
SET NullableDate = '20220317'
WHERE SomeColumn = 'wera';
GO
--Following fails (as now not NULL
UPDATE dbo.YourTable
SET NullableDate = NULL
WHERE SomeColumn = 'asda';
GO
SELECT *
FROM dbo.YourTable;
GO
DROP TABLE dbo.YourTable;
db<>fiddle
Change the part below from #Larnu 's answer,
IF EXISTS (SELECT 1 FROM inserted i
JOIN deleted d ON i.ID = d.ID
WHERE d.NullableDate IS NOT NULL
AND i.NullableDate IS NULL)
to below
IF EXISTS (SELECT 1 FROM deleted d WHERE d.NullableDate IS NOT NULL)
to get the exact behavior you want.
dbfiddle

How can I update the rows that are existed before the insert using Trigger ( SQL Server )?

I'm looking for a method to update old rows before an insert or update using a Trigger ,
For example , I have this table
ID PersonID Name Status
1 001 Alex False
2 002 Mark True
What I need exactly is that when I insert in this table a new row (3,003,Jane,True) , the column status should be affected to False ( all old rows ) only the new row will have True
So the expected result when applying the trigger will be like this :
ID PersonID Name Status
1 001 Alex False
2 002 Mark False
3 003 Jane True
How can I do this?
What I have tried:
ALTER TRIGGER [dbo].[dbo.TR_SetStatus] ON [dbo].[Person]
after INSERT
NOT FOR REPLICATION
AS
DECLARE #CursorTestID INT = 1;
DECLARE #RowCnt BIGINT = 0;
BEGIN
DECLARE #count INT;
SELECT #RowCnt = COUNT(*) FROM Person;
WHILE #CursorTestID <= #RowCnt
BEGIN
update Person set status=0
SET #CursorTestID = #CursorTestID + 1
END
END
I have two questions:
How can I update the rows that are existed before the insert using Trigger ( SQL Server )?
How can I pass a parameter to a trigger? (as an example PersonID)
DROP TABLE IF EXISTS dbo.Test;
CREATE TABLE dbo.Test
(
id tinyint identity(1,1)not null primary key,
person_id char(3)not null,
name varchar(50)not null,
status varchar(5) not null
)
insert dbo.Test(person_id,name,status)
values('001','alex','false'),('002','mark','true');
go
SELECT *FROM DBO.Test
DROP TRIGGER IF EXISTS dbo.II_Test;
GO
CREATE TRIGGER dbo.II_Test
ON dbo.Test
INSTEAD OF INSERT
AS
BEGIN
UPDATE DBO.Test SET status='FALSE';
INSERT DBO.Test(person_id,name,status)
SELECT I.person_id,I.name,I.status
FROM inserted AS I
END
GO
insert dbo.Test(person_id,name,status)
values('003','JANE','true');
select * from dbo.Test
Could you please check if the above is suitable for you
How can I update the rows that are existed before the insert using Trigger ( SQL Server )
For example, you can use INSTEAD OF-trigger
How can I pass a parameter to a trigger? (as an example PersonID)
This is not supported at all. If you need parameters the better way, I guess, is to use stored procedure
Finally, I solved my problem ( the first question ) :
ALTER TRIGGER [dbo].[dbo.TR_SetActive] ON [dbo].[test]
after INSERT
NOT FOR REPLICATION
AS
BEGIN
update dbo.test set status=0 WHERE Id < (SELECT MAX(Id) FROM dbo.test)
END
For the second question , I have used to get the last record as parameter:
set #PersonId = (select PersonId from inserted)
Can be simplfy with :
CREATE TRIGGER dbo.E_I_Test
ON dbo.Test
FOR INSERT
AS
BEGIN
UPDATE T
SET status = CASE WHEN I.id IS NULL THEN 0 ELSE 1 END
FROM dbo.Test as T
LEFT OUTER JOIN inserted AS I
ON T.id = I.id;
BEWARE.... status is a reserved Transact SQL keyword. Should not be use for any SQL identifier (table, name, column neme...)
Corrections made...

Trying to insert null data into a view in SQL, any other way?

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

How to get Identity of new records INSERTED into table with INSTEAD OF trigger

I am using an INSTEAD OF insert trigger on a table to set an incrementing version number on the row and also copy the row to a 2nd history/audit table.
The rows are inserted to both tables without a problem.
However, I am having trouble returning the new identity from the 1st table back to the user.
Schema
CREATE TABLE Table1
(
id INT IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(250) NOT NULL UNIQUE,
rowVersion INT NOT NULL
)
CREATE TABLE Table1History
(
id INT NOT NULL,
name VARCHAR(250) NOT NULL,
rowVersion INT NOT NULL
)
CREATE TRIGGER TRG_INS_Table1
ON Table1
INSTEAD OF INSERT
AS
DECLARE #OutputTbl TABLE (id INT, name VARCHAR(250))
BEGIN
--make the insert
INSERT INTO Table1 (name, rowVersion)
OUTPUT INSERTED.id, INSERTED.name INTO #OutputTbl(id, name)
SELECT i.name, 1
FROM INSERTED i
--copy into history table
INSERT INTO Table1History (id, name, rowVersion)
SELECT t.ID, i.name, 1
FROM INSERTED i
JOIN #OutputTbl t on i.name = t.name
END
CREATE TRIGGER TRG_UPD_Table1
ON Table1
INSTEAD OF UPDATE
AS
BEGIN
--make the update
UPDATE Table1
SET name = i.name,
rowVersion = (SELECT d.rowVersion + 1 FROM DELETED d WHERE d.id = i.id)
FROM INSERTED i
WHERE Table1.id = i.id
--copy into history table
INSERT INTO Table1History (id, name, rowVersion)
SELECT i.id ,i.name, (SELECT d.rowVersion + 1 FROM DELETED d WHERE d.id = i.id)
FROM INSERTED i
END
Joining on the name column in the insert trigger is not ideal, but it needs to handle multiple inserts at once.
eg INSERT INTO Table1 (name) VALUES('xxx'),('yyy')
Attempted Solutions
When doing an insert, SCOPE_IDENTITY is NULL.
INSERT INTO Table1(name)
VALUES('xxx')
SELECT SCOPE_IDENTITY()
or
INSERT INTO Table1(name)
VALUES('xxx')
RETURN SCOPE_IDENTITY()
I've also tried using OUTPUT - which returns 0:
DECLARE #IdentityOutput TABLE (id INT)
INSERT INTO Table1(name)
OUTPUT INSERTED.id INTO #IdentityOutput
VALUES('xxx')
SELECT id FROM #IdentityOutput
The rows are inserted fine and have IDs, but I cannot access them unless I use the below - which seems hacky:
INSERT INTO Table1(name)
VALUES('xxx')
SELECT id from Table1 WHERE name = 'xxx'
What is the proper way to get the new ID??
Solution
Impossible! You can't reliably return the identity when doing an INSERT on a table that has an INSTEAD OF trigger. Sidux's answer below is a good workaround for my situation (replace INSTEAD OF trigger with AFTER trigger and added DEFAULT columns).
CREATE TABLE Table1
(
id INT IDENTITY(1,1) PRIMARY KEY,
name VARCHAR(250) NOT NULL UNIQUE,
rowVersion INT NOT NULL
)
GO
CREATE TABLE Table1History
(
id INT NOT NULL,
name VARCHAR(250) NOT NULL,
rowVersion INT NOT NULL
)
GO
CREATE TRIGGER TRG_INS_Table1
ON Table1
INSTEAD OF INSERT
AS
DECLARE #OutputTbl TABLE (id INT, name VARCHAR(250))
BEGIN
--make the insert
INSERT INTO Table1 (name, rowVersion)
SELECT i.name, 1
FROM INSERTED i
END
GO
CREATE TRIGGER TRG_UPD_Table1
ON Table1
INSTEAD OF UPDATE
AS
BEGIN
--make the update
UPDATE Table1
SET name = i.name,
rowVersion = (SELECT d.rowVersion + 1 FROM DELETED d WHERE d.id = i.id)
FROM INSERTED i
WHERE Table1.id = i.id
END
GO
CREATE TRIGGER TRG_AFT_INS_Table1
ON Table1
AFTER INSERT, UPDATE
AS
BEGIN
INSERT INTO Table1History (id, name, rowVersion)
SELECT i.ID, i.name, i.rowversion
FROM INSERTED i
END
GO
INSERT INTO Table1 (name) VALUES('xxx'),('yyy')
SELECT * FROM Table1History
-----------------------------------------------
id name rowVersion
2 yyy 1
1 xxx 1
-----------------------------------------------
UPDATE Table1 SET name = 'xxx1' WHERE id = 1;
SELECT * FROM Table1History
-----------------------------------------------
id name rowVersion
2 yyy 1
1 xxx 1
1 xxx1 2
-----------------------------------------------
Basically you do not need TRG_INS_Table1 trigger, you can just use DEFAULT value = 1 for column and that's it. Also if you use DATETIME column instead of rowversion, you can just insert the state of INSERTED table to the history with the GETDATE() value. In that case you can order by Dtime column DESC and you have history.

How can I know that a Trigger is fired or not?

I am using SQL Server 2008 R2 on a windows 7 machine. I have a trigger that should be fired on an insert but unfortunately it does not. I do not have the SQL Profiler because I have an express edition. Is there any other way to see what is going wrong?. The insert into the table teams is done with the Import Wizard of SQL Server, an i import from .CSV into a table.
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
Okay. If we can change the table definitions of tblTeams and tblMatches slightly, so that they maintain their own ID columns using IDENTITY, then we can fix the trigger to be safe for multi-row inserts:
create table teams (
hometeam varchar(10) not null,
awayteam varchar(10) not null,
score int not null
)
create table tblteams (
teamId int IDENTITY(1,1) not null,
teamName varchar(10) not null
)
create table tblmatches (
matchId int IDENTITY(1,1) not null,
HomeTeamID int not null,
AwayTeamID int not null,
Score int not null
)
go
CREATE TRIGGER process ON teams
AFTER INSERT
AS
SET NOCOUNT ON
declare #TeamIDs table (TeamID int not null,TeamName varchar(10) not null)
;with AllTeams as (
select hometeam as teamName from inserted
union
select awayteam from inserted
)
merge into tblTeams tt using AllTeams at on tt.teamName = at.teamName
when matched then update set teamName = at.teamName
when not matched then insert (teamName) values (at.teamName)
output inserted.TeamID,inserted.teamName into #TeamIDs;
insert into tblmatches (HomeTeamID,AwayTeamID,Score)
select ht.TeamID,at.TeamID,i.Score
from inserted i
inner join #TeamIDs ht on i.hometeam = ht.TeamName
inner join #TeamIDs at on i.awayteam = at.TeamName
GO
And then we test it out:
insert into teams (hometeam,awayteam,score) values
('abc','def',10),
('def','ghi',5),
('jkl','mno',7)
go
insert into teams (hometeam,awayteam,score) values
('abc','ghi',19),
('pqr','stu',11)
go
select * from tblteams
select * from tblmatches
The issue with your existing trigger is it didn't cope with inserted containing multiple rows - the trigger is fired once per statement, not once per row. So e.g. these line are wrong:
SELECT #homeTeamId = #maxTeamId + 1
SELECT #maxTeamId = #maxTeamId + 1
INSERT INTO tblTeams SELECT #homeTeamId, i.hometeam FROM inserted i
Since there might be multiple homeTeam values to deal with.
It also didn't deal well with concurrency - two calls to the trigger happening in parallel might end up with the same #maxTeamId value - and then attempt to insert rows into tblTeam with the same TeamId values - whereas using IDENTITY columns, SQL Server deals with this for us automatically.
The only slight fudge in the above is using MERGE to insert new teams - the WHEN MATCHED line will do a No-Op UPDATE for existing rows (since we know the teamName matches on both sides), but it's a nice trick to do the lookup of existing rows and INSERT of new rows in a single statement.
I've just realised that you've said that you're using the Import data wizard. I have a feeling that the SSIS Package that it generates creates a destination using Fast Load, and doesn't specify FIRE_TRIGGERS. That could scupper you also.
You could either generate the package using the wizard, then edit the properties, or use the wizard to insert into a staging table, then do a plain INSERT/SELECT from that table into our teams table, and let the trigger fire that way.
Bulk insert wizards / data import wizards usually bypass triggers on the destination table.

Resources