Server query to find the current designation of the employee - sql

Table Employee:
ID, Designation, PromotionDate
Code:
ALTER FUNCTION GetTheDesignationEmployee
(#EmpID INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #Designation VARCHAR(25) = ''
SELECT #Designation = Designation
FROM Employee
WHERE PromotionDate = (SELECT MAX(PromotionDate)
FROM Employee
WHERE ID = #EmpID)
RETURN(#Designation)
END
If I run the code, I should get the current designation of the employee. I pass the ID, and should get back the corresponding current designation.
SELECT dbo.GetTheDesignationEmployee(5346)
But I get an error instead of an answer.

Most likely; if I interpret your last comment correctly, you're getting a designation with a proper date - but since you've forgot to limit the outer SELECT to use the #EmpID passed it, it might be someone else's (with the same PromotionDate)....
Try this:
ALTER FUNCTION GetTheDesignationEmployee
(#EmpID INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #Designation VARCHAR(25) = ''
SELECT #Designation = Designation
FROM EmployeeDetails
WHERE PromotionDate = (SELECT MAX(PromotionDate)
FROM EmployeeDetails
WHERE ID = #EmpID)
-- you need to also include the #EmpID here!
AND ID = #EmpID;
RETURN(#Designation)
END
Or you could write the whole function much simpler:
ALTER FUNCTION GetTheDesignationEmployee
(#EmpID INT)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #Designation VARCHAR(25) = ''
SELECT TOP (1) #Designation = Designation
FROM EmployeeDetails
WHERE ID = #EmpID
ORDER BY PromotionDate DESC;
RETURN(#Designation)
END
WORD of warning: scalar functions that are doing data access are notoriously bad for performance - so maybe you want to think about another way to get that "most recent designation" in your query to avoid having to write and use this function in the first place.

Related

SQL recursive udf always returns null

Create Table Employees
(
Employee varchar(10),
Manager varchar(10)
);
Insert into Employees
values
('Charlie',null),
('Peter','James'),
('Elai',null),
('Graham','Emanuel'),
('Amanda','Charlie'),
('Sen','Graham'),
('Emanuel',null),
('James','Amanda'),
('Elai',null),
('Victor','Elai');
Above "Employees" table contains employee and employee's manager name. When trying to retrieve comma separated hierarchy of a employee using below function, the result is always null.
for example :
employee 'Victor', hierarchy/result should be "Victor, Elai".
Could anyone point out what am I doing wrong in below UDF.
Create Function EmployeeHierarchy(#employeeName varchar(20))
Returns varchar(100)
AS
Begin
Declare #commaSeparatedHierarchy varchar(100);
Declare #manager varchar(20);
if(#employeeName is not null)
Begin
Select #manager=Manager from Employees where Employee=#employeeName;
Set #commaSeparatedHierarchy=dbo.EmployeeHierarchy(#manager)+','+#manager;
End
return #commaSeparatedHierarchy;
End;
First & foremost, you DO NOT want to create this as a scalar function. Their performance is horrible any udf you create, should be created as an inline table valued function. The following should do what you're looking for...
-- the test data...
USE tempdb;
GO
IF OBJECT_ID('tempdb.dbo.Employee', 'U') IS NOT NULL
DROP TABLE dbo.Employee;
CREATE TABLE dbo.Employee (
Employee varchar(10),
Manager varchar(10)
);
INSERT dbo.Employee (Employee, Manager) VALUES
('Charlie',null),
('Peter','James'),
('Elai',null),
('Graham','Emanuel'),
('Amanda','Charlie'),
('Sen','Graham'),
('Emanuel',null),
('James','Amanda'),
('Elai',null),
('Victor','Elai');
SELECT * FROM dbo.Employee e;
iTVF code...
CREATE FUNCTION dbo.EmployeeHierarchy
(
#employeeName varchar(20)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH
cte_Recur AS (
SELECT
CSH = CAST(CONCAT(e.Employee, ', ' + e.Manager) AS VARCHAR(1000)),
e.Manager,
NodeLevel = 1
FROM
dbo.Employee e
WHERE
e.Employee = #employeeName
UNION ALL
SELECT
CSH = CAST(CONCAT(r.CSH, ', ' + e.Manager) AS VARCHAR(1000)),
e.Manager,
NodeLevel = r.NodeLevel + 1
FROM
dbo.Employee e
JOIN cte_Recur r
ON e.Employee = r.Manager
WHERE
e.Manager IS NOT NULL
)
SELECT
commaSeparatedHierarchy = MAX(r.CSH)
FROM
cte_Recur r;
GO
Sample execution...
SELECT
eh.commaSeparatedHierarchy
FROM
dbo.EmployeeHierarchy('peter') eh;
... and the results...
commaSeparatedHierarchy
------------------------------
Peter, James, Amanda, Charlie

How can I assign value into difference parameter from the same time in SQL Server?

How can I assign value into difference parameter from the same time in SQL Server?
Example:
I have table that has columns age, name, address. How can I assign those values into the declared parameters #age int, #name varchar(max) and #address varchar(max)?
I wrote the following code, but it's not working
set #age = age,
set #name = name,
set #address = address
from [dbo].[test]
I don't know which DMBS you are using, but in mysql you can do this:
select #name := name, #age := age from dbo.test
Of course it will only store the field of the last row matched, so you will need to use an appropriate where clause to choose the row you are interested in.
You can also use the set command, but you will need a separate query for each field you want set:
set #name = (select name from dbo.test limit 1)
set #age = (select age from dbo.test limit 1)
SELECT #age = age,#name = name,#address = address FROM [dbo].[test]
SELECT #age = age,
#name = name,
#address = address
FROM dbo.test
WHERE primarykey = somevalue

How can I use <> operator and || operator inside a stored procedure

I have created an database file inside my asp.net application. Now from server explorer I tried to write a Stored procedure as follows
CREATE PROCEDURE insertData
(
#ID int,
#Name varchar(50),
#Address varchar(50),
#bit BIT OUTPUT
)
as
begin
declare #oldName as varchar(45)
declare #oldAddress as varchar(45)
set #oldName=(select EmployeeName from Employee where EmployeeName=#Name)
set #oldAddress=(select Address from Employee where Address=#Address)
if(#oldName <> #Name | #oldAddress <> #Address)
insert into Employee(EmpID,EmployeeName,Address)values(#ID,#Name,#Address)
SET #bit = 1
END
But this is giving me an error when I am saving it like Incorrect syntax near <..
There are several things wrong here
if(#oldName <> #Name | #oldAddress <> #Address)
Won't work - maybe try
if #oldName <> #Name OR #oldAddress <> #Address
Of course, this will never be true because of the way the two queries above (which could and should have just been one query assigning both variables) make sure that the variables are always equal.
I.e.:
set #oldName=(select EmployeeName from Employee where EmployeeName=#Name)
What can #oldName be, if not equal to #Name? (Okay, it could be NULL, but then <> is the wrong operator to use if NULL is what you're checking for)
I think that what you wanted to write here was:
select #oldName=EmployeeName,#oldAddress = Address from Employee where EmpID = #ID
You should use OR and not |
You can also do this instead of querying and checking each value separately, this will insert new row if name and/or address do not match for given empid
IF NOT EXISTS (
select * from Employee
where EmpID = #ID AND EmployeeName = #Name AND Address = #Address)
insert into Employee(EmpID,EmployeeName,Address)values(#ID,#Name,#Address)
SET #bit = 1
END
You can use != instead of "<>" and you can use Or instead of "|".

using IF and else in Where clause and using IN ( in where condition field)

I want to run the following query. #city value will be provided run time
Select * from Emp
where empno in (
if( #city = 'Bangalore')
Begin
Select Empno from Emp
where EmpCity = #city
End
Else
Begin
Select empno from Emp
End
)
Kindly help me by providing alternative
suppose your search is based upon EmpId -- #EmpId and City -- #city
Select *
from
Emp
where
(#city = '' or EmpCity = #city) and
(#EmpId = '' or EmpId = #EmpId)
IF is a control flow statement. You can't place statements inside other statements.
The usual thing people are looking for when they come up with IF is CASE, which is an expression. However, in this case, a far simpler query seems doable:
Select * from Emp
where
(EmpCity = #city or #city != 'Bangalore') and
(EmpSalary = #salary or #salary != 20000) and
(Designation = #designation or #designation != 'PM')
I don't see why you have the nested select at all

<table-valued function> is not a recognized built-in function name

I am getting this error:
Msg 195, Level 15, State 10, Line 1
'fnParseName' is not a recognized built-in function name.
On this query:
SELECT fnParseName(DOCTORFIRSTNAME+' ' +DOCTORLASTNAME)
FROM [PracticeandPhysician]
Here's the code for fnParseName
create FUNCTION [dbo].[fnParseName]
(#FullName NVARCHAR(128))
RETURNS #FullNameParts TABLE (FirstName NVARCHAR(128),
Middle NVARCHAR(128),
LastName NVARCHAR(128))
AS
BEGIN
... function body that populates #FullNameParts ...
RETURN
END
Why am I getting this error?
It's a table-valued function. So you probably meant:
SELECT p.DOCTORFISTNAME, p.DOCTORLASTNAME, t.FirstName, t.Middle, t.LastName
FROM dbo.[PracticeandPhysician] AS p
CROSS APPLY dbo.fnParseName(p.DOCTORFIRSTNAME + ' ' + p.DOCTORLASTNAME);
Note that you can't say:
SELECT dbo.TableValueFunction('foo');
Any more than you could say:
SELECT dbo.Table;
--or
SELECT dbo.View;
You can, however, say:
SELECT * FROM dbo.fnParseName('foo bar');
--or
SELECT FirstName, Middle, LastName FROM dbo.fnParseName('foo bar');
(Not that I have validated that your function does what you think, or does so efficiently.)
Please always use the dbo. prefix as others have suggested.
You always have to prefix SQL function calls with the schema name dbo. or the schema name for that function (dbo is the default schema).
SELECT dbo.fnParseName(--etc
UDFs/Functions need to be prefixed with the schema name (most likely "dbo"). Change the call to
SELECT
dbo.fnParseName(DOCTORFIRSTNAME + ' ' + DOCTORLASTNAME)
FROM
[PracticeandPhysician]
The problem you have is similar to what I encountered too. Scalar function and Table inline functions are quite different in terms of implementation. See below for the diiferent
Create function udfCountry
(
#CountryName varchar(50)
)
returns varchar(2)
as
BEGIN
Declare #CountryID varchar(2),
#Result varchar(2)
Select #CountryID = Country from
dbo.GeoIPCountryNames where CountryName = #CountryName
set #Result = isNull(#CountryID, 'NA')
if #Result = 'NA'
set #Result = 'SD'
return #Result
End
//Implementation
select dbo.[udfCountry]('Nigeria')
// sample result
NG
// Inline table function sample
Create FUNCTION ConditionEvaluation
(
#CountrySearch varchar(50)
)
returns #CountryTable table
(
Country varchar(2),
CountryName varchar(50)
)
as
Begin
Insert into #CountryTable(Country, CountryName)
Select Country, CountryName from GeoIPCountryNames
where Country like '%'+#CountrySearch+'%'
return
end
//Implementation sample
Declare #CountrySearch varchar(50)
set #CountrySearch='a'
select * from ConditionEvaluation(#CountrySearch)
the parttern of implementating scalar is quite different inline table. I hope this helps
If you want to assign the value returned by tfn in a variable of stored procedure, you can do it this way:
select #my_local_variable_in_procedure = column_name_returned_from_tfn from dbo.my_inline_tfn (#tfn_parameter)