SQL FUNCTION - one alias in SELECT AND WHERE - sql

I want to insert to NewTable some id(found by calledMethod) from table 'inserted' when this id actually it's not in this table(NewTable)
Actually i'm using this method (calledMethod)twice. How to reduce this using for example alias?
CREATE TRIGGER TriggerName
ON Table
AFTER INSERT
AS
BEGIN
INSERT INTO NewTable
(
FirstId
SecondId
)
SELECT
I.ID
CalledMethod(I.Name)
FROM INSERTED I
WHERE CalledMethod(I.Name)
NOT IN (SELECT SecondId FROM NewTable)
END
GO
The second problem occures when I want insert two rows at the same time.
Insert Into Table
(
Name
)
Values
('ro'),('ro-RO')
In this situation, the method returns the same index and both will be added. How to resolve this problem.
In this situation, the method returns the same index
This is example of calledMethod
CREATE FUNCTION CalledMethod
(
#internalName nvarchar(50)
)
RETURNS int
AS
BEGIN
return case
when #internalName Like 'ro%' then 6
when #internalName Like 'sk%' then 7
when #internalName Like 'bg%' then 9
end
END

I believe this is what you need:
CREATE TRIGGER TriggerName
ON Table
AFTER INSERT
AS
BEGIN
INSERT INTO NewTable
(
FirstId
SecondId
)
SELECT
min(I.ID),
x.called
FROM INSERTED I
CROSS APPLY
(SELECT CalledMethod(I.Name) called) x
WHERE
x.called NOT IN (SELECT SecondId FROM NewTable)
GROUP BY x.called
END

Related

how to see difference between 2 tables

I have 2 tables: 1 temp and the other one is my main table.
Each day I would update my temp table and I want to update my main table based on the changes I made from the temp table.
Example: The first temp table contains an id and name. Then I insert the value from temp into the main table. But when I made changes from my temp like insert another id and name, I want my main table to compare and only insert the unique id from the temp table.
As you said, it seems like you have a table object named as temp table. If this is the case then you may use after insert trigger on temp table to insert new inserted value in your main table.
CREATE TRIGGER AfterINSERTTrigger on [Temptable]
FOR INSERT
AS DECLARE #id INT,
#col1 VARCHAR(50),
.
.
SELECT #id = ins.id FROM INSERTED ins;
SELECT #col1 = ins.col1 FROM INSERTED ins;
.
.
INSERT INTO [MainTable](
[id]
,[col1]
.
.)
VALUES (#id,
#col1,
.
.
.
);
PRINT 'We Successfully Fired the AFTER INSERT Triggers in SQL Server.'
GO
Similarly you can update your table on update of record in temptable using update trigger. You may find this link on more info on trigger. LINK
OR
If you are creating temp table object to get the new inserted record then use simple not in or not exists clause to get the newly inserted record.
Using NOT IN
insert into maintable ( id, col1, ...)
select Id , col1, .... from temptable
where id not in (select id from maintable)
Using NOT EXISTS
insert into maintable ( id, col1, ... )
select id, col1, ... from temptable as temp
where not exists (select id from maintable as main where main.id=temp.id)
You can use NOT EXISTS as follows
INSERT into main_table(
id, name,
...
)
SELECT
id,name,
...
FROM temp_table t
WHERE
NOT EXISTS(
SELECT 1
FROM main_table m
WHERE m.id = t.id
)
Cheers!!

Delete From Where In Select, will no results in the select delete anything?

I have some Delete statements in a stored procedure to delete some child records in other tables, and eventually delete the ID passed to the stored procedure.
I'm concerned about what happens if one of the select statements used with the Delete returns nothing, will this delete anything on that table?
Example
DELETE FROM [tblPurchases]
WHERE [ID] IN (SELECT [ID] FROM #PurchaseIDs)
In the case (from your example), when SELECT [ID] FROM #PurchaseIDs will not return anything, nothing will be deleted from tblPurchases because ID in (empty_set) condition will not be met.
by the way - you can easily check it by yourself, for example like this:
declare #t1 table (ID int)
insert into #t1 (ID)
select 1
union all
select 2
union all
select 3
declare #t2 table (ID int)
insert into #t2 (ID)
select 1
delete from #t1 where ID in (select ID from #t2 where ID > 1)
select * from #t1
Answer is no , nothing will be deleted. Nothing is "in" an empty collection, so nothing will be deleted.

Table-valued function - duplicate table declaration

I am using table-valued function in SQL Server to return data either with ties or without on some condition specified.
Now the solution works fine but I do not like the fact that I have to declare the table twice - is there any workaroud? I could probably instead of inserting into #tmp table use #ReturnTable but that data would have to be deleted once select top 1 is queried at the end of the function.
RETURNS #ReturnTable TABLE
(
idTable INT,
idOther INT,
name VARCHAR(30)
)
AS
BEGIN
DECLARE #tmp TABLE
(
idTable INT,
idOther INT,
name VARCHAR(30)
)
INSERT INTO #tmp
SELECT idTable,
idOther,
name
FROM SomeTable
IF (some condition)
BEGIN
INSERT INTO #ReturnTable
SELECT TOP 1 WITH TIES idTable,
idOther,
name
FROM #tmp
ORDER BY (some ordering)
END;
ELSE
BEGIN
INSERT INTO #ReturnTable
SELECT TOP 1 idTable,
idOther,
name
FROM #tmp
ORDER BY (some other ordering)
END;
RETURN;
END;
Try re-writing your function to Inline table valued function.
Based on the condition you have to use either ROW_NUMBER or DENSE_RANK window function. TOP 1 with TIES can be achieved using DENSE_RANK/RANK
RETURNS TABLE
AS
RETURN
(SELECT idtable,
idother,
NAME
FROM (SELECT CASE
WHEN (some condition) THEN Dense_rank()OVER(ORDER BY (some ordering))
ELSE Row_number()OVER(ORDER BY (some other ordering))
END AS RN,
idtable,
idOther,
NAME
FROM sometable)a
WHERE RN = 1)

Inserting temp table values into a table.

I have a temp table declared
declare #tmptable(
value nvarchar(500) not null
);
I use a function to insert values into that temp table.
I am trying to figure out how to update a table using the values of #tmptable
insert into t1 (
active
,SchoolId
,inserted
)
select
1
,temp.value
,#insertedDate
select temp.value from #tmptable;
When i try to insert in table t1 it doesn't work. I guess there are two Select statements is causing the problem. Please let me know how to fix it. Thanks
Try this one -
INSERT INTO dbo.t1
(
Active
, SchoolId
, Inserted
)
SELECT
1
, t.value
, #insertedDate
FROM #tmptable t;
INSERT INTO t1
(
ACTIVE
,SchoolId
,INSERTED
)
SELECT 1
,temp.value
,#insertedDate
FROM #tmptable temp;
insert into t1 (
active
,SchoolId
,inserted
)
select
1
,temp.value
,#insertedDate
from #tmptable;
this will work...

issue with trigger in ms sql server?

IF EXISTS (SELECT name FROM sysobjects WHERE name = 'myTrigger' AND type = 'TR')
BEGIN
DROP TRIGGER myTrigger
END
GO
go
create trigger myTrigger
on mytable_backup
instead of insert
as
begin
declare #seq int
select #seq = seq from inserted
if exists (select * from mytable_backup where seq= #seq) begin
delete from mytable_backup where seq=#seq
end
insert into mytable_backup
select * from inserted
end
go
I've written this trigger to check while inserting if seq column is repeated then update the previous row with same seq if seq doesn't exits insert it with new seq.
In ssis package I'm using OLEDB table(Mytable) as a source which contains.
Name,Age,Seq
Gauraw,30,1
Gauraw,31,1
Kiran,28,3
Kiran,29,3
kiran,28,3
Venkatesh,,4
Venkatesh,28,4
Now I'm loading this table to OLEDB destination(Mytable_backup) as destination.
I suppose to get output as.
Gauraw,31,1
kiran,28,3
Venkatesh,28,4
But I'm getting all the records from Mytable into Mytable_backup.
is anything wrong with my trigger?
I think that this trigger will just take the first row and compare it with the existing. If I understand what you want to do you can quit easy do this:
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'myTrigger' AND type = 'TR')
BEGIN
DROP TRIGGER myTrigger
END
GO
go
create trigger myTrigger
on mytable_backup
instead of insert
as
begin
insert into mytable_backup
select
*
from
inserted
WHERE NOT EXISTS
(
SELECT
NULL
FROM
mytable_backup AS mytable
WHERE
inserted.seq=mytable.seq
)
end
go
EDIT
So I found out what was going on. If you insert all of the rows in one go the inserted contains all the rows.. Sorry my mistake. If there are duplicates in your data your example do not show which to choose. I have chosen the one with the maximum of age (don't know what your requirements is). Here is a update with the full example
Table structure
CREATE TABLE mytable_backup
(
Name VARCHAR(100),
Age INT,
Seq INT
)
GO
Trigger
create trigger myTrigger
on mytable_backup
instead of insert
as
begin
;WITH CTE
AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY inserted.Seq ORDER BY Age) AS RowNbr,
inserted.*
FROM
inserted
WHERE NOT EXISTS
(
SELECT
NULL
FROM
mytable_backup
WHERE
mytable_backup.Seq=inserted.Seq
)
)
insert into mytable_backup(Age,Name,Seq)
SELECT
CTE.Age,
CTE.Name,
cte.Seq
FROM
CTE
WHERE
CTE.RowNbr=1
end
GO
Insert of test data
INSERT INTO mytable_backup
VALUES
('Gauraw',30,1),
('Gauraw',31,1),
('Kiran',28,3),
('Kiran',29,3),
('kiran',28,3),
('Venkatesh',20,4),
('Venkatesh',28,4)
SELECT * FROM mytable_backup
Drop of the database objects
DROP TRIGGER myTrigger
DROP TABLE mytable_backup
Your original code has two flaws:
It assumes that only one record is inserted at a time.
Your insert into mytable_backup happens outside of the if condition. That insert will execute every time.