I want to declare a function in SQL SERVER, It is the beginning of my code, but I get this error: 'CREATE FUNCTION' must be the only statement in the batch.
CREATE FUNCTION FindingMobileOrTelephone ( #Number nchar(11) )
RETURNS nvarchar
AS
BEGIN
DECLARE #ItIsMobile nvarchar;
DECLARE #ItIsTelephone nvarchar;
RETURNS #ItIsMobile;
END;
what is the problem?!
try this
Last Statement Should be RETURN not RETURNS
CREATE FUNCTION FindingMobileOrTelephone ( #Number nchar(11) )
RETURNS nvarchar
AS
BEGIN
DECLARE #ItIsMobile nvarchar;
DECLARE #ItIsTelephone nvarchar;
RETURN (#ItIsMobile);
^
END
CREATE FUNCTION/TABLE should be the first statement in the script you're executing.
One option was already mentioned. Adding GO kind of splits the script into separate ones.
However, if you have this within BEGIN END block this won't work since you can't split this block with GO.
An option here is to wrap CREATE statment into a string literal and use EXEC or sp_executesql
-- your script
EXEC('CREATE FUNCTION ... END')
Related
In SQL Server I want to create a function similar to the avg where I receive the column name as a parameter and query a table to get the values for the specified column.
Maybe this is not possible as I saw that I cannot use exec for the common solution outside functions that is to concatenate the query string and execute it.
create function myAvg(#columnName varchar(255))
returns float
as
begin
declare #queryStr varchar(255) = '(select AVG(cast(' + #columnName + ' as float)) from functionTest)';
return execute( #queryStr);
end
I get this error:
RETURN statements in scalar valued functions must include an argument
Another solution with cursors:
create function myAvg (#columnName varchar(255))
returns float
as
begin
declare #MyCursor as cursor;
declare #value float;
declare #total float = 0.0;
declare #nElems int = 0;
set #MyCursor = cursor for
select #columnName from functionTest;
open #MyCursor;
fetch next from #MyCursor into #value;
while ##FETCH_STATUS = 0
begin
set #total = #total + #value;
set #nElems = #nElems + 1;
fetch next from #MyCursor into #value;
end
close #MyCursor;
deallocate #MyCursor;
return #total /#nElems
end
Calling the cursor solution throws this error:
Error converting data type varchar to float
I guess functions can't be that versatile with dynamic column parameterization.
Is there an alternative?
Edited: I know I can do this in a stored procedure but then I can't call it from a query.
Thanks
You cannot do what you want to do.
First, you cannot replace an identifier -- such as a column name -- with a parameter. That is simply not how parameters work. They only replace constant values.
Second, a function cannot execute dynamic SQL. You can get around the first problem using dynamic SQL, but that is not allowed in a function.
So, you cannot have a function that takes a column names as an argument and returns the average.
Instead, you can just use a window function in the outer query:
select . . . ,
avg(column_name) over ()
from . . .;
Note: There actually is a way using a very complicated method of re-invoking a query in SQL Server, but it is not worth it.
you cannot use execute in functions. for this purpose is better to use CLR functions.
https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/create-clr-functions?view=sql-server-2017
Create a SQL stored procedure that parses a string into previously unknown number of fields. The inputs would be
a text string of undetermined length;
a delimiter, passed as a string;
a nullable column that, if relevant, would pass the text indicator as a single character string.
The resulting table would be entirely dependent on the string used as an input
Please help because I cannot figure this out. I know this is wrong, but I had no clue where to begin.
Here is what I have tried so far:
DECLARE #l INT, #c VARCHAR(MAX) = ''
SELECT #l = MAX(LEN(n)) FROM AdventureWOrk
DECLARE #s NVARCHAR(MAX) = '
;WITH cte AS
)
Insert INTO #Values (1, 'CGID', 'EENumber', 'EEYID', 'SSN' )
SELECT
[Value],
[Value],
Prod_Attributes.value('/Attribute[1]','varchar(MAX)') AS [CGID],
Prod_Attributes.value('/Attribute[2]','varchar(MAX)') AS [EENUMBER],
Prod_Attributes.value('/Attribute[3]','varchar(MAX') AS [EYEID],
Prod_Attributes.value('/Attribute[4]','varchar(MAX') AS [SSN]
You can create a stored procedure by using the following syntax:
CREATE PROCEDURE usp_YourProcedure
AS
BEGIN
-- Your logic
END
You would put the code you already have within the BEGIN statement.
To execute the stored procedure you can do:
EXEC usp_YourProcedure
To add parameters, simply state them after the CREATE PROCEDURE declaration.
CREATE PROCEDURE usp_YourProcedure
(
#TextField VARCHAR(MAX),
#Delimeter VARCHAR(1),
#TextIndicator CHAR(1) = NULL
)
AS
BEGIN
END
Then to execute with parameters:
EXEC usp_YourProcedure 'String literal, with commas, which will, be stripped out by the delimiter', ','
Further details are outlined at MSDN.
As an additional note, try keeping your variable names descriptive and consistent, also check the casing.
CREATE PROCEDURE <ProcedureName>
-- Add the parameters for the stored procedure here
<Param1>, <Param2> ...
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
END
GO
When I execute this query select 1/0 in sql server, it will show this Message:
Msg 8134, Level 16, State 1, Line 16 Divide by zero error encountered.
I need a function to get Number of error. for this example output of my function should be 8134
how can I create this function to get my required result?
CREATE FUNCTION GetErrorNumber
(
#command NVARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
--function Body
END
If you are going to pass the error message to function, then try this:
CREATE FUNCTION Fun_GetErrorNumber
(
#command NVARCHAR(MAX)
)
RETURNS INT
AS
BEGIN
RETURN CAST(SUBSTRING(#q,PATINDEX('%[0-9]%',#q),PATINDEX('%,%',#q)-PATINDEX('%[0-9]%',#q)) AS INT)
END
But if you want to pass the query to function, you should take note that executing command inside Function is not valid and you need to use stored procedure instead. Like this:
CREATE PROCEDURE Pro_Execute
(
#command NVARCHAR(MAX) ,
#num INT OUTPUT
)
AS
BEGIN
BEGIN TRY
EXEC(#command);
SET #num = 0;
END TRY
BEGIN CATCH
SET #num = ERROR_NUMBER();
END CATCH;
END;
And call it like this:
DECLARE #res INT
EXEC Pro_Execute 'Select 1/0' ,#num = #res output
SELECT #res
The above SP will get the command and execute it. If non-fatal error occurred while executing the command, error number will be returned.
Reading this article may help you decorate your solution in better way
If I understand the question, you want to parse the error message and get the number between Msg and ,.
This seems like a simple string manipulation to me:
CREATE FUNCTION GetErrorNumber
(
#command nvarchar(max)
)
RETURNS int
AS
BEGIN
SELECT CAST(SUBSTRING(#command, 5, CHARINDEX(',', #command, 5) - 5) as int)
END
Though I do agree with juergen d - simply using the built in ERROR_NUMBER() seems better in most cases.
As described in this answer, You can't.
When you want to check your command you need to execute that command that it is impossible in body of a function.
I have the below code where im using ISnumeric function to check the validity of an expression to do the math in sql.
But if I use ISnumeric function here it returns 0 for both the two conditons listed below. I need some function or a method to identify a valid mathematical expression.
Is there any alternative for this one ?
Begin
DECLARE #rcnt as VARCHAR(100)
DECLARE #ncnt as VARCHAR(100)
--Condition1
SET #rcnt = '(5918800.000 / 4963400.000) * (Slaughter(1023))'
--Condition2
SET #ncnt = '(5997200.000 / 5059900.000) * (400000.000)'
Select ISNUMERIC(#rcnt) as validittcheck
Select ISNUMERIC(#ncnt ) as validittcheck
END
ISNUMERIC() is a check that a variable is a valid numeric datatype, not that the result of the evaluation of a string expression is a valid numeric value. Your values became non-numeric as soon as the first '(' was evaluated.
The only way I know to get the desired result is to use dynamic sql. Here is an example, notice I put the try catch in there because your Slaughter() function does not exist and an exception is raised, so return zero as it is not a number:
DECLARE #rcnt as NVARCHAR(100)
DECLARE #ncnt as NVARCHAR(100)
--Condition1
SET #rcnt = 'SELECT #Result=ISNUMERIC( (5918800.000 / 4963400.000) * (Slaughter(1023)) )'
--Condition2
SET #ncnt = 'SELECT #Result=ISNUMERIC( (5997200.000 / 5059900.000) * (400000.000) )'
DECLARE #ResultValue1 INT=0
DECLARE #ResultValue2 INT=0
DECLARE #ResultParam NVARCHAR(100)= '#Result int OUTPUT'
BEGIN TRY
EXEC sp_executesql #rcnt, #ResultParam, #Result=#ResultValue1 OUTPUT
END TRY
BEGIN CATCH
END CATCH
BEGIN TRY
EXEC sp_executesql #ncnt, #ResultParam, #Result=#ResultValue2 OUTPUT
END TRY
BEGIN CATCH
END CATCH
SELECT #ResultValue1
SELECT #ResultValue2
I create a function to execute dynamic SQL and return a value. I am getting "Only functions and some extended stored procedures can be executed from within a function." as an error.
The function:
Create Function fn_GetPrePopValue(#paramterValue nvarchar(100))
returns int as
begin
declare #value nvarchar(500);
Set #SQLString = 'Select Grant_Nr From Grant_Master where grant_id=' + #paramterValue
exec sp_executesql
#query = #SQLString,
#value = #value output
return #value
end
The execution:
Select dbo.fn_GetPrePopValue('10002618') from Questions Where QuestionID=114
and:
Select fn_GetPrePopValue('10002618') from Questions Where QuestionID=114
Is the function being called properly or is the function incorrect?
You cannot use dynamic SQL from a function, neither can you call
stored procedures.
Create proc GetPrePopValue(#paramterValue nvarchar(100))
as
begin
declare #value nvarchar(500),
#SQLString nvarchar(4000)
Set #SQLString = 'Select #value = Grant_Nr From Grant_Master where grant_id = #paramterValue'
exec sp_executesql #SQLString, N'#paramterValue nvarchar(100)',
#paramterValue,
#value = #value output
return #value
end
Functions are limited in what they can use, so that you can use them in a query without accidentally make something that would give horrible performance. Using dynamic queries is one of those things, as that would cause a query planning for each execution, and also would keep the function from being able to be part of a query plan.
You don't need the dynamic query at all in this case, just return the value:
Create Function fn_GetPrePopValue(#paramterValue nvarchar(100))
returns int as
begin
return (select Grant_Nr From Grant_Master where grant_id = #paramterValue)
end
I don't think you can use dynamic SQL from a function, nor do I think you need to in your case. Looks like you want something closer to this:
Create Function dbo.fn_GetPrePopValue(#paramterValue nvarchar(100))
returns int as
begin
declare #value int
declare #SQLString varchar(MAX)
Select #value=Grant_Nr From Grant_Master where grant_id=#paramterValue
return #value
end
SQL Fiddle Demo
Also, please check your data types to make sure you're fields are correct. Seems odd to pass in a varchar for the id and return an int for the other field. Either way, this should help you get going in the right direction.