using if statement in sql function - sql-server

i have a code like this
create function factfind(#num integer)
returns integer
as
begin
if (#num=1) then
return 1;
else
return(#num*factfind(#num-1));
end if;
end
errors was that,
Msg 156, Level 15, State 1, Procedure factfind, Line 5
Incorrect syntax near the keyword 'then'.
Msg 156, Level 15, State 1, Procedure factfind, Line 7
Incorrect syntax near the keyword 'else'.
Msg 195, Level 15, State 10, Procedure factfind, Line 8
'factfind' is not a recognized built-in function name.
please help me friends.

...
begin
return ( CASE
WHEN #num=1 THEN 1
ELSE #num * dbo.factfind(#num-1)
END
);
end
Edit: needs to be dbo.factfind because scalar udfs must be schema qualified

Execute this:
CREATE FUNCTION dbo.fakultät(#n DECIMAL(38,0))
RETURNS DECIMAL(38,0)
AS
BEGIN
DECLARE #tmp DECIMAL(38,0)
IF (#n <= 1)
SELECT #tmp = 1
ELSE
SELECT #tmp = #n * dbo.fakultät(#n - 1)
RETURN #tmp
END
or:
CREATE FUNCTION dbo.Factorial ( #iNumber int )
RETURNS INT
AS
BEGIN
DECLARE #i int
IF #iNumber <= 1
SET #i = 1
ELSE
SET #i = #iNumber * dbo.Factorial( #iNumber - 1 )
RETURN (#i)
END

The problem you have is in part the syntax of the if statement in TSQL, the right thing to do is:
create function factfind(#num integer)
returns integer
as
begin
declare #Result int
set #Result = 1
if (#num>1)
set #Result = #num * dbo.factfind(#num-1);
return #Result
end

Related

Why do variables not work with TOP command?

Why does below SQL script throw errors?
Is this issue with TOP command?
Or is it because of the SELECT statement which does not support SQL variables?
My code:
DECLARE #cnt INTEGER = 0;
Declare #cnt_total INT;
SET #cnt_total = 5
WHILE (#cnt < #cnt_total)
BEGIN
SET #cnt = #cnt + 1;
SELECT TOP #cnt *
FROM FOCUSCDR.PATIENTDXHISTORY
END;
Error:
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near '#cnt'.
While above works when used.
SELECT TOP 1 *
FROM FOCUSCDR.PATIENTDXHISTORY
Because the syntax requires parentheses:
DECLARE #cnt INTEGER = 0;
Declare #cnt_total int ;
Set #cnt_total = 5
WHILE (#cnt < #cnt_total)
BEGIN
SET #cnt = #cnt + 1;
Select top (#cnt) * from FOCUSCDR.PATIENTDXHISTORY
END;
Edit:
As mentioned in the comment by #Tim Biegeleisen, you should be using ORDER BY, otherwise it makes no sense using TOP since the order will not be guaranteed and you might get non consistent results. Check out this article for more info on it.

Error on Alter Table-valued Function with Native Compilation in SQL Server 2016

I have the following script that alters my native compiled function. I want it to return a Table. I am also altering from single statement into multi statement. so I am changing returns to begin atomic.
ALTER FUNCTION [dbo].[MovieSimularity]
(
#movieID int
)
RETURNS #result Table (movieID int, distance int)
WITH Native_Compilation, SCHEMABINDING
as
Begin ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'English')
--begin
declare #m int
declare #countZero int
declare #r Table (movieID int, distance int)
declare cur cursor local for
select movieID
from dbo.Movies
where movieID != #movieID and dbo.CompareMovieHashes(#movieID, movieID) = 1
open cur
fetch next from cur into #m
while ##FETCH_STATUS = 0
begin
insert into #r
select #m, dbo.MovieEuclideanDistance(#movieID,#m) as distance
set #countZero = (select count(*) from #r where distance = 0)
if(#countZero > 5)
break
fetch next from cur into #m
end
close cur
deallocate cur
return
select top(5) *
from #r
order by distance
end
The execution gives me the following errors:
Msg 487, Level 16, State 1, Procedure MovieSimularity, Line 12 [Batch Start Line 7]
An invalid option was specified for the statement "CREATE/ALTER FUNCTION".
Msg 319, Level 15, State 1, Procedure MovieSimularity, Line 13 [Batch Start Line 7]
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Procedure MovieSimularity, Line 44 [Batch Start Line 7]
Incorrect syntax near 'end'.
I don't know what is the problem. Please Help
BEGIN ATOMIC is part of the ANSI SQL standard. SQL Server supports
atomic blocks at the top-level of natively compiled stored procedures,
as well as for natively compiled, scalar user-defined functions. For
more information about these functions, see Scalar User-Defined
Functions for In-Memory OLTP.
https://learn.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/atomic-blocks-in-native-procedures
Atomic is not supported by Table-Valued functions (as per the docs), only be Scalar-Valued functions.
What is wrong with this query? Why do you need the cursor?
DECLARE #movieID INT = 1;
SELECT TOP(5)
movieID
, dbo.MovieEuclideanDistance(#movieID,m.movieID) AS distance
FROM
dbo.Movies
WHERE
movieID != #movieID
AND dbo.CompareMovieHashes(#movieID, movieID) = 1
ORDER BY
distance
Here is a solution to your 0 distance problem without using cursors or loops. Adjust it to your needs.
DECLARE
#rowsToCalculate INT = 5
, #currentX DECIMAL(8,5)
, #currentY DECIMAL(8,5)
;
-- Get the current movie's X and Y coordinates
SELECT
, #currentX = CoordX
, #currentY = CoordY
FROM
dbo.Movies
WHERE
MovieID = #movieID
;
-- First get the list with distance 0 (x and y coordinates are equal)
INSERT INTO #result (MovieID int, Distance int)
SELECT TOP(#rowsToCalculate)
MovieID
, 0 AS Distance
WHERE
CoordX = #currentX
AND CoordY = #currentY
AND MovieID != #movieID
AND dbo.CompareMovieHashes(#movieID, MovieID) = 1
;
-- Figure out how many records do we need and get them if there is any.
SET #rowsToCalculate = #rowsToCalculate - (SELECT COUNT(*) FROM #result);
IF (#rowsToCalculate > 0) BEGIN
INSERT INTO #result (MovieID int, Distance int)
SELECT TOP(#rowsToCalculate)
movieID
, dbo.MovieEuclideanDistance(#movieID,m.movieID) AS distance
FROM
dbo.Movies
WHERE
movieID != #movieID
AND dbo.CompareMovieHashes(#movieID, MovieID) = 1
AND (CoordX != #currentX OR CoordY != #currentY)
ORDER BY
Distance
END

Msg 248, Level 16, State 1, Line 1 The conversion of the varchar value '60811404740101-60811404740102' overflowed an int column

I am getting errors with the following stored procedure. I'd like to say that I am new to SQL and currently not up to par yet but anyway, here is the values I'm passing:
USE [AFCache]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[csp_WellTestValidationResults_GetData]
#ColumnName = N'API14-2',
#ColumnValue = N'60811404740101-60811404740102'
SELECT 'Return Value' = #return_value
GO
and here is the actual stored procedure:
ALTER PROCEDURE [dbo].[csp_WellTestValidationResults_GetData]
-- Declare variables that will get data passed from PIAF to query data
(#ColumnName varchar(max) = 'Blank',
#ColumnValue varchar(max) = 'Blank')
AS
BEGIN
SET NOCOUNT ON;
IF (#ColumnName = 'API14-2')
BEGIN
DECLARE #APIStrip varchar(max);
SET #APIStrip = SUBSTRING(#ColumnName, 0, CHARINDEX('- ', #ColumnName, 0));
DECLARE #LeftNumber varchar(max);
SET #LeftNumber = SUBSTRING(#ColumnValue, 0, CHARINDEX('-', #ColumnValue, 0));
DECLARE #RightNumber varchar(max)
SET #RightNumber = SUBSTRING(#ColumnValue, CHARINDEX('-', #ColumnValue, 0) + 1, LEN(#ColumnValue));
EXEC('Select * from dbo.SSIS_RTRM_WellTestValidationResults where '+#APIStrip+' = '+#LeftNumber+' OR '+#APIStrip+' = '+#RightNumber+' order by TestDate Desc')
END
IF (#ColumnName = 'API14')
BEGIN
EXEC('Select * from dbo.SSIS_RTRM_WellTestValidationResults where '+#ColumnName+' = '''+#ColumnValue+''' order by AssetName, ReservoirName, API14, TestDate Desc')
END
IF (#ColumnName <>'AssetName') or (#ColumnName <>'ReservoirName') or (#ColumnName <>'FieldName')
BEGIN
EXEC('Select wtvv.* from dbo.SSIS_RTRM_WellTestValidationResults wtvv join '+'(select WellId, Max(TestDate) AS TestDate from dbo.SSIS_RTRM_WellTestValidationResults wtv group by WellId)'+' wtvv1 on wtvv1.WellId = wtvv.WellId and wtvv1.TestDate = wtvv.TestDate where '+#ColumnName+' = '''+#ColumnValue+''' order by AssetName, ReservoirName, API14')
END
IF (#ColumnName <>'AssetName') or (#ColumnName <>'ReservoirName') or (#ColumnName<> 'FieldName')or (#ColumnName <>'API14-2')or (#ColumnName <>'API')
BEGIN
SELECT *
FROM dbo.SSIS_RTRM_WellTestValidationResults
WHERE WellId = ''
END
END
When I execute the query I keep getting the following error:
Msg 248, Level 16, State 1, Line 1
The conversion of the varchar value '60811404740101-60811404740102' overflowed an int column.
I have gone through the code and I don’t understand where is my problem and why am I getting this error.
Looks like the SSIS_RTRM_WellTestValidationResults table has an int column for API14-2. It would help if you posted your table schema as well.
Without seeing your table schema I can only presume your using a standard int data type for API14 column. Looking at your code your splitting the large number on the dash (-). This is leaving you with the number 60,811,404,740,101 and 60,811,404,740,102 for the left and right sides. This far exceeds the max int value of 2,147,483,647. You will need to update your column data type to be bigint which has a max value of 9,223,372,036,854,775,807
Try replacing this line:
DECLARE #return_value int
With this:
DECLARE #return_value [numeric](18, 0)

Incorrect syntax near '=' near WHILE LOOP

I've wirtten below script, but when i try to execute it give below err -
Msg 102, Level 15, State 1, Line 6 Incorrect syntax near '='.
declare #PostDate date
declare #PostID int
DECLARE #count INT
DECLARE #updatecounter INT
WHILE exists (select top 1 #PostDate = postdate from dateTemp order by postdate desc)
BEGIN
PRINT #PostDate
SELECT #count = COUNT(*) from cs_posts_bkup20160209 where CONVERT(date,Postdate) = #PostDate
print #COUNT
SET #updatecounter = 1
WHILE (#count>=1)
BEGIN
select top 1 #PostID = PostId from cs_posts_bkup20160209 where CONVERT(date,Postdate) = #PostDate and Postorder IS NULL order by postdate desc
pRINT #POSTID
--update cs_posts_bkup20160209 set PostOrder = #updatecounter where postid= #PostID
SET #updatecounter = #updatecounter + 1
SET #count = #count - 1
Print #updatecounter
Print #count
END
DELETE from dateTemp where Postdate = #PostDate
END
GO
what i am missing here...
please help!!
If you assign a variable in a select, the select will not also return a result set - and a result set is required for EXISTS.
Easiest fix is probably to re-run the query that sets #PostDate inside your loop and remove the assignment from the query used by the while loop.

Split function getting error

Below code i am using for MSSQL 2005,but when i try to run in MSSQL 2000 i am getting below erros.
Msg 156, Level 15, State 1, Procedure StrSplit, Line 5
Incorrect syntax near the keyword 'WITH'.
Msg 170, Level 15, State 1, Procedure StrSplit, Line 15
Line 15: Incorrect syntax near ')'.
CREATE FUNCTION dbo.StrSplit (#sep char(1), #s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(#sep, #s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(#sep, #s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(#s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
Thanks in advance
Use the below function in its place.
CREATE FUNCTION [dbo].[fn_Split](#text VARCHAR(8000), #delimiter VARCHAR(20) = ' ')
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #text = LTRIM(RTRIM(#text))
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
Hope this helps!!
CTE's - IE "WITH" are a feature starting in sql 2005. Not available in 2000...
You cannot use CTE's (Common Table Expressions - WITH) in SQL Server 2000. They were introduced in SQL Server 2005.

Resources