Incorrect syntax near '<' in SQL Server Scalar Functions - sql

Here is the requirement:
Find all teachers whose FirstName length is less than 5 and the first 3 characters of their FirstName and LastName are the same
I tried this query (Scalar Function):
CREATE OR ALTER FUNCTION dbo.fn_TeacherFirstName (#TeacherID int)
RETURNS NVARCHAR(20)
AS
BEGIN
DECLARE #Result NVARCHAR(20)
SELECT #Result = LEN(FirstName) < 5 AND LEFT(FirstName,3) = LEFT(LastName,3)
FROM dbo.Teacher
WHERE #TeacherID = ID
RETURN #Result
END
To call function:
--CALL FUNCTION
select *, dbo.fn_TeacherFirstName (ID) AS Result
from dbo.Teacher t
But, when I execute first query, it shows error:
Incorrect syntax near '<'.
Can anyone help me with this?

Just use a normal query, not a function. Also there is no boolean type in SQL Server, use bit instead.
SELECT *,
Result = CAST(CASE WHEN LEN(t.FirstName) < 5 AND LEFT(t.FirstName, 3) = LEFT(t.LastName, 3) THEN 1 END AS bit)
FROM dbo.Teacher t

Related

Multiple errors in SQL Server Function

I'm trying to make a function that evaluates the expiration date in a policy and based on that when is called in a Query it returns the text values ('Monthly'..and so on). but i'm getting a few errors of type "Incorrect syntax near Begin, declare expecting (.", "Must declare the scalar variable #policybillid" and in the end of the function "Incorrect syntax near ')'.". Any help would be appreciated.
USE [defaultDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID]( #policybillid BIGINT, #companyID BIGINT) Returns TABLE
AS
RETURN (
BEGIN( ***Incorrect syntax near 'BEGIN'. Expecting '(', SELECT, or WITH.***
declare #expiresDates as table(expiredOn date) ***Incorrect syntax near 'declare'.*** Expecting '(', or SELECT.
insert into #expiresDates
select top(2) expiredOn from PolicyPaymentPlan
left join PolicyPaymentPlanFee on PolicyPaymentPlan.paymentPlanID= PolicyPaymentPlanFee.paymentPlanID
where PolicyPaymentPlan.policyBillID = #policybillid --Must declare the scalar variable "#policybillid".
order by cuoteID
select * from #expiresDates
declare #diffMonth int
declare #quota varchar(max) = ''
if((select count(*) from #expiresDates) > 1)
BEGIN
set #diffMonth = DATEDIFF(month, (select top(1) expiredOn from #expiresDates), (select top(1) expiredOn from #expiresDates order by expiredOn desc));
set #quota = ( SELECT
CASE
WHEN #diffMonth =1
then
'Monthly'
WHEN #diffMonth =2 THEN
'bimonthly'
WHEN #diffMonth =3 THEN
'trimonthly '
WHEN #diffMonth =4 THEN
'Four-Monthly'
WHEN #diffMonth =6 THEN
'biannual'
ELSE 'Cash'
END
)
END
) ***Incorrect syntax near ')'.***
There are numerous issues and syntax errors on your existing code. The main one is that an inline Table Valued Function can only have a single SELECT statement and nothing else.
So here is what it should look like.
CREATE OR ALTER FUNCTION [dbo].[fn_Payment_GetPaymentCoutesByPaymentID](
#policybillid BIGINT,
#companyID BIGINT
)
RETURNS TABLE
AS RETURN
SELECT Quota =
CASE WHEN COUNT(*) > 1 THEN
CASE DATEDIFF(month, MIN(expiredOn), MAX(expiredOn))
WHEN 1 THEN 'Monthly'
WHEN 2 THEN 'bimonthly'
WHEN 3 THEN 'trimonthly '
WHEN 4 THEN 'Four-Monthly'
WHEN 6 THEN 'biannual'
ELSE 'Cash'
END
END
FROM (
select top (2) expiredOn
from PolicyPaymentPlan pp
join PolicyPaymentPlanFee ppf on pp.paymentPlanID = ppf.paymentPlanID
where pp.policyBillID = #policybillid
order by cuoteID
) pp
;

"select into" in select statement

I need this query inside a select statement in another query, i have tried to put it inside a function and call it from the select, but i get errors maybe because non-scalar statements are not allowed in a function. How can i proceed?
SELECT Tip.NombreTipoMov
INTO #tabla_temp
FROM ut_sgt_Movimientos_t Reg
INNER JOIN ut_sgt_TiposMovimientos_m Tip
ON Reg.id_TipoMov = Tip.id_TipoMov
WHERE Reg.id_Registro = #IdRegistro
DECLARE #data VARCHAR(100)
UPDATE #tabla_temp
SET #data = #data + ' ' + NombreTipoMov
SELECT LTRIM(RTRIM(#data))
DROP TABLE #tabla_temp
This is the function:
CREATE FUNCTION dbo.uf_sgt_ObtieneTiposMovimientosXRegistroVehiculo
(
#IdRegistro INTEGER
)
RETURNS VARCHAR(100)
AS
BEGIN
DECLARE #Retorno VARCHAR(100)
SET #Retorno = ( SELECT Tip.NombreTipoMov
INTO #tabla_temp
FROM ut_sgt_Movimientos_t Reg
INNER JOIN ut_sgt_TiposMovimientos_m Tip
ON Reg.id_TipoMov = Tip.id_TipoMov
WHERE Reg.id_Registro = #IdRegistro
DECLARE #data VARCHAR(100)
UPDATE #tabla_temp
SET #data = #data + ' ' + NombreTipoMov
SELECT LTRIM(RTRIM(#data))
DROP TABLE #tabla_temp
)
RETURN #Retorno END GO
This is the error:
Incorrect syntax near the keyword 'INTO'.
Illegal UPDATE statement within a scalar SQL function.
Illegal SELECT statement within a scalar SQL function.
Illegal DROP TABLE statement within a scalar SQL function.
Incorrect syntax near ')'.

Issues with SQL Max function: "Incorrect syntax new the keyword 'SELECT' "

I'm trying to write a stored procedure to return the maximum value of a column + 1 but for some reason it doesn't want to work.
DECLARE #ID int;
SET #ID = SELECT MAX(ID) + 1 FROM tbl;
I can't for the life of me see what is wrong.
It gives me the error of:
incorrect syntax new the keyword 'SELECT'
No need for SET. Select value directly:
DECLARE #ID int;
SELECT #ID = MAX(ID) + 1 FROM tbl;
Use parentheses ( ... ):
DECLARE #ID int;
SET #ID = (SELECT MAX(ID) + 1 FROM tbl);
or SELECT as suggested by Giorgi. SET is the ANSI standard way of assigning values to variables, SELECT is not. Apart from that using SELECT to assign values to variables is fine, it allows even multiple assignments with one SELECT.
But in general your query seems to be a race condition. Use an IDENTITY column if you want to autoincrement a value. Auto increment primary key in SQL Server Management Studio 2012
You need to consider a scenario when there is no value in the table and MAX returns NULL.
DECLARE #ID int;
SELECT #ID = ISNULL(MAX(ID) , 0) + 1 FROM tbl;
Other adding 1 to null will always yield null.
DECLARE #ID int;
SET #ID = (SELECT MAX(ID) + 1 FROM tbl);
parentheses operator ()
for more information
https://msdn.microsoft.com/en-us/library/ms190276.aspx

how to return a cell into a variable in sql functions

I want to define a scaler function which in that I'm going to return the result into a variable but I do not know how to do this.
CREATE FUNCTION dbo.Funname ( #param int )
RETURNS INT
AS
declare #returnvar int
select #returnvar = select colname from tablename where someconditions = something
return(#returnvar)
I want to make a function something like the top. I mean the result of the select statement which is:
select colname from tablename where someconditions = something
Is only a single cell and we are sure about it. I want to store it into a variable and return it from the function. How can I implement this thing?
I should probably mention that scalar UDFs do come with a considerable health warning and can cause performance issues depending upon how you use them.
Here's an example though.
CREATE FUNCTION dbo.Funname ( #param INT )
RETURNS INT
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN (SELECT number FROM master.dbo.spt_values WHERE number < #param)
END
In the above example I didn't use a variable as it is redundant. The version with variable is
BEGIN
DECLARE #Result int
SET #Result = (SELECT number FROM master.dbo.spt_values WHERE number < #param)
RETURN #Result
END
For both of the above you would need to be sure the Query returned at most one row to avoid an error at runtime. For example
select dbo.Funname(-1) Returns -32768
select dbo.Funname(0) Returns error "Subquery returned more than 1 value."
An alternative syntax would be
BEGIN
DECLARE #Result int
SELECT #Result = number FROM master.dbo.spt_values WHERE number < #param
RETURN #Result
END
This would no longer raise the error if the subquery returned more than one value but you would just end up with an arbitrary result with no warning - which is worse.
Following Comments I think this is what you need
CREATE FUNCTION dbo.getcustgrade(#custid CHAR(200))
RETURNS INT
WITH RETURNS NULL ON NULL INPUT
AS
BEGIN
RETURN
( SELECT [cust grade]
FROM ( SELECT customerid,
DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS [cust grade]
FROM Orders
GROUP BY CustomerID
)
d
WHERE customerid = #custid
)
END

SQL UDF Group By Parameter Issue

I'm having some issues with a group by clause in SQL. I have the following basic function:
CREATE FUNCTION dbo.fn_GetWinsYear (#Year int)
RETURNS int
AS
BEGIN
declare #W int
select #W = count(1)
from tblGames
where WinLossForfeit = 'W' and datepart(yyyy,Date) = #Year
return #W
END
I'm trying to run the following basic query:
select dbo.fn_GetWinsYear(datepart(yyyy,date))
from tblGames
group by datepart(yyyy,date)
However, I'm encountering the following error message: Column 'tblGames.Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Any ideas why this is occurring? FYI, I know I can remove the function and combine into one call but I'd like to keep the function in place if possible.
I think you should be calling your function like this.
select dbo.fn_GetWinsYear(datepart(yyyy,getdate()))
OR
select dbo.fn_GetWinsYear('2010')
Essentially you are just passing a year to your function and the function is returning the number of wins for that year.
If you don't know the year, your function could look something like this...
CREATE FUNCTION dbo.fn_GetWinsYear ()
RETURNS #tblResults TABLE
( W INT, Y INT )
AS
BEGIN
INSERT #tblResults
SELECT count(1), datepart(yyyy,[Date])
FROM tblGames
WHERE WinLossForfeit = 'W'
GROUP BY datepart(yyyy,[Date])
RETURN
END
SELECT * FROM dbo.fn_GetWinsYear()