Create T-SQL Function with table parameter - sql

I needed to write function with table parameter.
an example:
CREATE FUNCTION getParentByBrandList
( #_BrandList TABLE(
BR_ID INT, BR_Name NVARCHAR(150), BR_ParentBrandID INT, BR_MasterBrandID INT, BR_Role INT,
BR_State INT, BR_OwnerID INT, BR_OwnerIP NVARCHAR(50), BR_CreateDate DATETIME, BR_UpdaterID INT,
BR_UpdaterIP NVARCHAR(50), BR_UpdateDate DATETIME
)
)
How can I do?
Thanx

Beginning from SQL Server 2008 you can use table valued parameters:
CREATE TYPE [dbo].[TableType] AS TABLE(
[ID] [INT] NULL
)
GO
CREATE FUNCTION fnTest
(
#t [dbo].[TABLETYPE] READONLY
)
RETURNS INT
AS
BEGIN
RETURN (SELECT TOP 1 ID FROM #t ORDER BY id DESC)
END
GO
DECLARE #t [dbo].[TABLETYPE]
INSERT INTO #t
VALUES ( 1 ),
( 2 )
SELECT dbo.fnTest(#t) AS ID
Output:
ID
2

Check this tutorial
Example : Passing Table Valued Parameter to a function
/* CREATE USER DEFINED TABLE TYPE */
CREATE TYPE StateMaster AS TABLE
(
StateCode VARCHAR(2),
StateDescp VARCHAR(250)
)
GO
/*CREATE FUNCTION WHICH TAKES TABLE AS A PARAMETER */
CREATE FUNCTION TableValuedParameterExample(#TmpTable StateMaster READONLY)
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #StateDescp VARCHAR(250)
SELECT #StateDescp = StateDescp FROM #TmpTable
RETURN #StateDescp
END
GO

Try this...
CREATE FUNCTION getParentByBrandList ( )
RETURNS #_BrandList TABLE
(
BR_ID INT
,BR_Name NVARCHAR(150)
,BR_ParentBrandID INT
,BR_MasterBrandID INT
,BR_Role INT
,BR_State INT
,BR_OwnerID INT
,BR_OwnerIP NVARCHAR(50)
,BR_CreateDate DATETIME
,BR_UpdaterID INT
,BR_UpdaterIP NVARCHAR(50)
,BR_UpdateDate DATETIME
)
AS
BEGIN
--code to create/populate table
END;
You seem to be missing the returns, I have added the place-holder for the code. Also, since the name suggests Get By, you might be intensing to supply a parameter? if so, you just add to the parenthesis...
getParentByBrandList ( param)

This function is from AdevnrtureWorks2012 db from Microsoft which they provide for study purpose.
ALTER FUNCTION [dbo].[ufnGetContactInformation](#PersonID int)
RETURNS #retContactInformation TABLE
(
-- Columns returned by the function
[PersonID] int NOT NULL,
[FirstName] [nvarchar](50) NULL,
[LastName] [nvarchar](50) NULL,
[JobTitle] [nvarchar](50) NULL,
[BusinessEntityType] [nvarchar](50) NULL
)
AS
-- Returns the first name, last name, job title and business entity type for the specified contact.
-- Since a contact can serve multiple roles, more than one row may be returned.
BEGIN
IF #PersonID IS NOT NULL
BEGIN
IF EXISTS(SELECT * FROM [HumanResources].[Employee] e
WHERE e.[BusinessEntityID] = #PersonID)
INSERT INTO #retContactInformation
SELECT #PersonID, p.FirstName, p.LastName, e.[JobTitle], 'Employee'
FROM [HumanResources].[Employee] AS e
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = e.[BusinessEntityID]
WHERE e.[BusinessEntityID] = #PersonID;
IF EXISTS(SELECT * FROM [Purchasing].[Vendor] AS v
INNER JOIN [Person].[BusinessEntityContact] bec
ON bec.[BusinessEntityID] = v.[BusinessEntityID]
WHERE bec.[PersonID] = #PersonID)
INSERT INTO #retContactInformation
SELECT #PersonID, p.FirstName, p.LastName, ct.[Name], 'Vendor Contact'
FROM [Purchasing].[Vendor] AS v
INNER JOIN [Person].[BusinessEntityContact] bec
ON bec.[BusinessEntityID] = v.[BusinessEntityID]
INNER JOIN [Person].ContactType ct
ON ct.[ContactTypeID] = bec.[ContactTypeID]
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = bec.[PersonID]
WHERE bec.[PersonID] = #PersonID;
IF EXISTS(SELECT * FROM [Sales].[Store] AS s
INNER JOIN [Person].[BusinessEntityContact] bec
ON bec.[BusinessEntityID] = s.[BusinessEntityID]
WHERE bec.[PersonID] = #PersonID)
INSERT INTO #retContactInformation
SELECT #PersonID, p.FirstName, p.LastName, ct.[Name], 'Store Contact'
FROM [Sales].[Store] AS s
INNER JOIN [Person].[BusinessEntityContact] bec
ON bec.[BusinessEntityID] = s.[BusinessEntityID]
INNER JOIN [Person].ContactType ct
ON ct.[ContactTypeID] = bec.[ContactTypeID]
INNER JOIN [Person].[Person] p
ON p.[BusinessEntityID] = bec.[PersonID]
WHERE bec.[PersonID] = #PersonID;
IF EXISTS(SELECT * FROM [Person].[Person] AS p
INNER JOIN [Sales].[Customer] AS c
ON c.[PersonID] = p.[BusinessEntityID]
WHERE p.[BusinessEntityID] = #PersonID AND c.[StoreID] IS NULL)
INSERT INTO #retContactInformation
SELECT #PersonID, p.FirstName, p.LastName, NULL, 'Consumer'
FROM [Person].[Person] AS p
INNER JOIN [Sales].[Customer] AS c
ON c.[PersonID] = p.[BusinessEntityID]
WHERE p.[BusinessEntityID] = #PersonID AND c.[StoreID] IS NULL;
END
RETURN;
END;

Related

Join Tables using multiple fields across multiple tables

I am trying to join tables based on multiple fields, one from the immediate table and one from an adjoined table.
I would like to join the "Equipment" to "Contract Detail" on ContractDetailID only if Equipment CustomerID = Contract CustomerID.
Thank you in advance
declare #contract as table(
contractid int,
customerid int
)
declare #contractDetail as table(
contractDetailId int,
ContractID int
)
declare #equipment as table(
equipmentId int,
contractDetailId int,
CustomerId int
)
insert into #contract values(5,3)
insert into #contractDetail values(10,5)
insert into #equipment values(1,10,3)
select e.*
from
#contract c inner join
#contractDetail cd on (c.contractId = cd.contractID) inner join
#equipment e on (c.customerId = e.CustomerId and e.contractDetailId = cd.contractDetailId)

How can I pull data from multiple sql tables using a join statement

I'm designing a simple in-office ticket system, and would like to include a field for the party responsible for the next action. To do so right this moment I'm thinking of using tableName and tableID as specifiers for the specific responsible party (could be a technician, customer, or third party, all in different tables)
It would be fine to pull that data in and run another select call using the name of the table as a parameter, but the extra data flow slows things down significantly.
Is there a way to use a single join statement to return the details of the party with a column for the table name and one for the individual table id or is there a better way to store the data from multiple potential tables?
You can use left join to achieve your requirement :-
Set Nocount On;
Declare #OfficeTickets Table
(
Id Int Identity(1,1)
,Column1 Varchar(100)
,PartyType Varchar(1)
,TechnicianId Int Null
,CustomerId Int Null
,ThirdPartyId Int Null
)
Declare #OfficeTickets1 Table
(
Id Int Identity(1,1)
,Column1 Varchar(100)
,TableName Varchar(100)
,TableId Int Null
)
Declare #Technician Table
(
Id Int Identity(1,1)
,TechnicianName Varchar(100)
)
Declare #Customers Table
(
Id Int Identity(1,1)
,CustomerName Varchar(100)
)
Declare #ThirdParty Table
(
Id Int Identity(1,1)
,ThirdPartyName Varchar(100)
)
Insert Into #Technician(TechnicianName) Values
('Technician_1')
,('Technician_2')
,('Technician_3')
Insert Into #Customers(CustomerName) Values
('Customer_1')
,('Customer_2')
,('Customer_3')
Insert Into #ThirdParty(ThirdPartyName) Values
('ThirdParty_1')
,('ThirdParty_2')
,('ThirdParty_3')
,('ThirdParty_4')
Insert Into #OfficeTickets(Column1,PartyType,TechnicianId,CustomerId,ThirdPartyId) Values
('ABC','T',3,Null,Null)
,('XYZ','C',Null,2,Null)
,('PUQ','P',Null,Null,4)
Insert Into #OfficeTickets1(Column1,TableName,TableId) Values
('ABC','Technician',3)
,('XYZ','Customers',2)
,('PUQ','ThirdParty',4)
---- taken separate columns for parties
Select ot.Id
,ot.Column1
,t.TechnicianName
,c.CustomerName
,tp.ThirdPartyName
From #OfficeTickets As ot
Left Join #Technician As t On ot.PartyType = 'T' And ot.TechnicianId = t.Id
Left Join #Customers As c On ot.PartyType = 'C' And ot.CustomerId = c.Id
Left Join #ThirdParty As tp On ot.PartyType = 'P' And ot.ThirdPartyId = tp.Id
---- by TableName and TableId
Select ot.Id
,ot.Column1
,t.TechnicianName
,c.CustomerName
,tp.ThirdPartyName
From #OfficeTickets1 As ot
Left Join #Technician As t On ot.TableName = 'Technician' And ot.TableId = t.Id
Left Join #Customers As c On ot.TableName = 'Customers' And ot.TableId = c.Id
Left Join #ThirdParty As tp On ot.TableName = 'ThirdParty' And ot.TableId = tp.Id
output:-

SQL join with previous row from the same group

I have a problem with sql query. I'm trying to create one time script which will put data to table. I have temporary table of new values ordered by date and i'm going to search previous value which have to have the same GroupId, TransactionId and FieldTypeId but ClaimModificationId have to be smaller.
Below i write a script which would be good if not error throwing on line:
where m2.ClaimModificationId < m1.ClaimModificationId
sql does not allow do referer to m1 table. Is there a method to write that condition differently?
create table #modifications (
[ClaimModificationId] INT IDENTITY(1,1),
[GroupId] INT,
[FieldTypeId] INT,
[FieldName] NVARCHAR(255),
[TransactionId] INT,
[NewValue] NVARCHAR(255),
[UserEmail] NVARCHAR(255),
[ModificationDate] DATETIME,
[Action] NVARCHAR(50))
select top 10
m1.[GroupId],
m1.[FieldTypeId],
m1.[FieldName],
m1.[TransactionId],
cm4.[NewValue] as OldValue,
m1.[NewValue],
m1.[UserEmail],
m1.[ModificationDate],
m1.[Action]
from #modifications m1
left join (
select max(m2.ClaimModificationId) as ClaimModificationId, m2.[GroupId], m2.[FieldTypeId], m2.TransactionId
from #modifications m2
where m2.ClaimModificationId < m1.ClaimModificationId
group by m2.GroupId, m2.FieldTypeId, m2.TransactionId) m3
on m3.groupId = m1.GroupId and m3.FieldTypeId = m1.FieldTypeId and m3.TransactionId = m1.TransactionId
LEFT JOIN #modifications cm4 ON m3.ClaimModificationId = cm4.ClaimModificationId
Try with OUTER APPLY:
SELECT TOP 10
m1.[GroupId] ,
m1.[FieldTypeId] ,
m1.[FieldName] ,
m1.[TransactionId] ,
cm4.[NewValue] AS OldValue ,
m1.[NewValue] ,
m1.[UserEmail] ,
m1.[ModificationDate] ,
m1.[Action]
FROM #modifications m1
OUTER APPLY ( SELECT MAX(m2.ClaimModificationId) AS ClaimModificationId ,
m2.[GroupId] ,
m2.[FieldTypeId] ,
m2.TransactionId
FROM #modifications m2
WHERE m2.ClaimModificationId < m1.ClaimModificationId
AND m2.groupId = m1.GroupId
AND m2.FieldTypeId = m1.FieldTypeId
AND m2.TransactionId = m1.TransactionId
GROUP BY m2.GroupId ,
m2.FieldTypeId ,
m2.TransactionId
) m3
LEFT JOIN #modifications cm4 ON m3.ClaimModificationId = cm4.ClaimModificationId
you can try something like this
create table #modifications
(
[ClaimModificationId] INT IDENTITY(1,1),
[GroupId] INT,
[FieldTypeId] INT,
[FieldName] NVARCHAR(255),
[TransactionId] INT,
[NewValue] NVARCHAR(255),
[UserEmail] NVARCHAR(255),
[ModificationDate] DATETIME,
[Action] NVARCHAR(50)
)
INSERT INTO #modifications values(1,1,'field',2,'new val1','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(1,2,'field',2,'val1','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(2,1,'field',3,'val2','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(1,1,'field',2,'val3','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(1,1,'field',2,'val4','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(1,1,'field',2,'val5','email#email.com',GETDATE(),'inserted')
INSERT INTO #modifications values(2,1,'field',3,'val5','email#email.com',GETDATE(),'inserted')
SELECT TOP 10
m1.[GroupId],
m1.[FieldTypeId],
m1.[FieldName],
m1.[TransactionId],
LAG([NewValue]) OVER(PARTITION by GroupId, FieldTypeId, TransactionId ORDER BY ClaimModificationId ASC) as OldValue,
m1.[NewValue],
m1.[UserEmail],
m1.[ModificationDate],
m1.[Action]
from #modifications m1

"Invalid Column" when using column from table variable

I'm trying to declare a table variable and then join it to a table I created in the database. Every time I try to insert my "NAME" field into my table, I get the error 'Invalid Column Name "NAME"', even though the GNAME field works fine. What am I doing wrong, and how can I join me NAME column?
DECLARE #Names TABLE
(
ID INT,
NAME VARCHAR(100),
GNAME VARCHAR(100)
)
INSERT INTO #Names
(
ID,
NAME,
GNAME
)
SELECT
CName.ID,
Ref.NAME,
Ref.GNAME
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.ID = Ref.ID
IF ( OBJECT_ID('dbo.ReportTable', 'U') IS NOT NULL)
DROP TABLE dbo.ReportTable
CREATE TABLE [dbo].[ReportTable]
(
[ID_NUMBER] [INT],
[NAME] [VARCHAR](150)
[GNAME] [VARCHAR](150)
)
INSERT INTO [dbo].[ReportTable]
(
ID_NUMBER,
NAME,
GNAME
)
SELECT
C.ID_NUMBER,
N.NAME,
N.GNAME
FROM
#Names AS N
INNER JOIN
#CurrentPositions AS C
ON N.ID_NUMBER = C.ID_NUMBER
Try using a Temp table :
CREATE TABLE #Names
(
ID INT,
NAME VARCHAR(100),
GNAME VARCHAR(100)
)
INSERT INTO #Names
(
ID,
NAME,
GNAME
)
SELECT
CName.ID,
Ref.NAME,
Ref.GNAME
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.ID = Ref.ID
IF ( OBJECT_ID('dbo.ReportTable', 'U') IS NOT NULL)
DROP TABLE dbo.ReportTable
CREATE TABLE [dbo].[ReportTable]
(
[ID_NUMBER] [INT],
[NAME] [VARCHAR](150)
[GNAME] [VARCHAR](150)
)
INSERT INTO [dbo].[ReportTable]
(
ID_NUMBER,
NAME,
GNAME
)
SELECT
C.ID_NUMBER,
N.NAME,
N.GNAME
FROM
#Names AS N
INNER JOIN
#CurrentPositions AS C
ON N.ID_NUMBER = C.ID_NUMBER
I've assumed that you will also change the table variable #CurrentPositions to a temp table
Just remember to drop the tables after you use them.
It is quite possible that all you need to do is wrap your field names in square brackets, e.g.
INSERT INTO #Names
(
[ID],
[NAME],
[GNAME]
)
SELECT
CName.[ID],
Ref.[NAME],
Ref.[GNAME]
FROM
#CurrentPositions AS CName
LEFT OUTER JOIN
dbo.NameField AS Ref
ON
CName.[ID] = Ref.[ID]
If that doesn't fix it, please post the schema of your #CurrentPositions and dbo.NameField tables.

INSERT from JOIN inserts null values

The need to insert values from 3 tables into another table called myTable. The required fields in myTable are:
[Id_student] int,
[id_subjects] int
[degrees] float
[st_Name] nvarchar(30)
[Id_Class] int
[Id_Group] int
[Class] nvarchar(15)
[group] nvarchar(15))` ..
I created the stored procedure below. But after viewing the table I found that only the passed parameters were saved! ie #Id_student , #id_subjects , #degrees. Can anyone explain what is wrong with this code?
CREATE storedprocedure mySp_myTable_insert
#Id_student int,
#id_subjects int,
#degrees int
as
DECLARE #st_Name nvarchar(30)
SELECT #st_Name = pst.st_Name FROM dbo.sudents AS pst where pst.id_student=#id_student ;
INSERT [myTable]
(
[Id_student],
[id_subjects],
[degrees],
[st_Name],
[Id_Class],
[Id_Group],
[Class],
[group]
)
(select
#Id_student,
#id_subjects,
#degrees,
#st_Name
,tc.Id_Class
,tg.Id_Group
,tc.Class
,tg.group
from dbo.subjects sbj
inner join tGroup tg
inner join tClass tc
on tc.Id_Class=tg.Id_Class
on sbj.Id_Group =tg.Id_Group
where sbj.id_subjects=#id_subjects)
I think you should drop the parentheses around the SELECT statement and fix the order of the join-on keywords/clauses.
Try this version:
CREATE storedprocedure mySp_myTable_insert
#Id_student int,
#id_subjects int,
#degrees int
as
DECLARE #st_Name nvarchar(30)
SELECT #st_Name = pst.st_Name FROM dbo.sudents AS pst where pst.id_student=#id_student ;
INSERT [myTable]
(
[Id_student],
[id_subjects],
[degrees],
[st_Name],
[Id_Class],
[Id_Group],
[Class],
[group]
)
select
#Id_student,
#id_subjects,
#degrees,
#st_Name
,tc.Id_Class
,tg.Id_Group
,tc.Class
,tg.group
from dbo.subjects sbj
inner join tGroup tg on sbj.Id_Group =tg.Id_Group
inner join tClass tc on tc.Id_Class=tg.Id_Class
where sbj.id_subjects=#id_subjects
GO