I keep getting this error: Any Ideas?
Invalid use of side-effecting or time-dependent operator in 'newid' within a function.
I am working with MS-SQL Server 2005. Here is the T-SQL statement:
Create Function [dbo].[GetNewNumber]( )
RETURNS int
AS
BEGIN
Declare #code int
set #code = (SELECT CAST(CAST(newid() AS binary(3)) AS int) )
RETURN (#code)
END
You can't use NEWID() within a function.
A usual workaround (in my experience, it's more been the need for GETDATE()) is to have to pass it in:
Create Function [dbo].[GetNewNumber](#newid UNIQUEIDENTIFIER )
RETURNS int
AS
BEGIN
Declare #code int
set #code = (SELECT CAST(CAST(#newid AS binary(3)) AS int) )
RETURN (#code)
END
And call it like:
SELECT dbo.GetNewNumber(NEWID())
The function will not let you use the NewID, but this can be worked around.
Create View vwGetNewNumber
as
Select Cast(Cast(newid() AS binary(3)) AS int) as NextID
Create Function [dbo].[GetNewNumber] ( ) RETURNS int
AS
BEGIN
Declare #code int
Select top 1 #code=NextID from vwGetNewNumber
RETURN (#code)
END
Then you can use select dbo.[GetNewNumber]() as planned.
Does this have to be done with a function call? Whenever I needs this functionality, I just use:
checksum(newid())
This will generate negative numbers -- if they must be positive, you could use
abs(checksum(newid()))
Related
I'm trying to create a function that SUMs the total number of minutes of actual duration for videos with a Finished status given a UserID as a parameter. This is what I have so far but I can't figure out how to add the parameter for the Finished status. This comes from a different table of Status that has a StatusID and StatusText. Or would I do a NOT NULL statement?
CREATE FUNCTION dbo.vc_VideoRunTime(#userID int)
RETURNS int AS
BEGIN
DECLARE #returnValue int
SELECT #returnValue = DATEDIFF (n, StartDateTime, EndDateTime) FROM vc_Video
WHERE vc_Video.vc_UserID = #userID
RETURN #returnValue
END
GO
If your finished status is represented as a NULL endtime, then your function is fine:
CREATE FUNCTION dbo.vc_VideoRunTime (
#userID int
)
RETURNS int AS
BEGIN
DECLARE #returnValue int;
SELECT #returnValue = SUM(DATEDIFF(minute, v.StartDateTime, v.EndDateTime))
FROM vc_Video v
WHERE v.vc_UserID = #userID ;
RETURN #returnValue;
END;
GO
Why? The DATEDIFF() will return NULL if either argument is NULL. The SUM() will then return NULL.
Note that I changed the n to minute. This is much more readable. (I don't know anyone who uses the "n" option for "minute", it makes me think "nanosecond".)
If you actually want the function to return 0 in this case, then use COALESCE():
RETURN COALESCE(#returnValue, 0);
I am getting the follow error when trying to create the following function:
Error 1 SQL80001: Incorrect syntax near 'RETURN SELECT CAST( RAND(
#offset * #seed )* #max as int ) + 1'
What am I doing wrongly?
CREATE FUNCTION [dbo].[fn_RandomInt]( #offset int, #seed int, #max int )
RETURNS INT
AS
RETURN
SELECT CAST( RAND( #offset * #seed )* #max as int ) + 1
Is it possible to create a UDF that will accept a SEED into the Rand() function?
Correct syntax to create a function would be:
CREATE FUNCTION [dbo].[fn_RandomInt]( #offset int, #seed int, #max int )
RETURNS INT
AS
begin
RETURN CAST( RAND( #offset * #seed )* #max as int ) + 1
end
GO
But then you're going to get the error:
Msg 443, Level 16, State 1, Procedure fn_RandomInt, Line 5 Invalid use
of a side-effecting operator 'rand' within a function.
This is because you can't put indeterminate functions inside a UDF. Your functions can use views or procedures that use indeterminate functions though for some reason, so you could create a stored procedure with an output variable that returns the value of the rand function and use it. You could also just send the output of a rand function to the function and use it instead. Like:
select dbo.fn_RandomInt(10, rand(#seed), 20)
Also, if you're trying to get your function to return a random number between #offset and #max, then your formula will not work. You'd want something more like:
CAST(#offset + RAND(#seed) * (#offset-#max+1) as int)
You can get the reason it wont work with this syntax which will give you this error.
CREATE FUNCTION [dbo].[fn_RandomInt]( #offset int, #seed int, #max int )
RETURNS INT
AS
BEGIN
DECLARE #v_offset INT, #v_seed INT, #v_max INT, #result INT
SELECT #result = CAST(RAND( #v_offset * #v_seed ) * #v_max as int ) + 1
RETURN #result
END
It will give you this error -
Msg 443, Level 16, State 1, Procedure RandFn, Line 7
Invalid use of a side-effecting operator ‘rand’ within a function
You can look here for help but you will need to do something different either way since you want to feed RAND() arguments, so the view idea wouldn't work.
http://blog.sqlauthority.com/2012/11/20/sql-server-using-rand-in-user-defined-functions-udf/
Surprisingly there isn't any straight forward example to demonstrate the use of delimiter in Stored Procedure?
I have a string variable as input (with delimiter) and would like to make it as condition in Stored Procedure. Something like below:
CREATE PROCEDURE testing
(
#stringVar NVARCHAR(255) = NULL
)
....
BEGIN
Select * from table where column not in (#stringVar)
.....
END
Sample value for #stringVar will be a~b~c~d
How should I handle such case? Is there any built-in delimiter function in Sql Server?
From SQL Server 2008 on, you can use table valued parameters.
I cannot explain it better than here: http://www.sommarskog.se/arrays-in-sql.html
it is a bit of tricky situation and there is no "Simple way" of doing it. but I can give you the simplest way of doing it.
You will need to do two things to make this work,
1) Create a Split function which takes a parameter of deliminited
string and split these values. 2) Make your stored procedure in a
way that passed deliminited string is passed to that function and then
splited values are passed to the stored procedure
Split Function
CREATE FUNCTION [dbo].[FnSplit]
(
#List nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table (Id int identity(1,1),Value nvarchar(100))
AS
BEGIN
While(Charindex(#SplitOn,#List)>0)
Begin
Insert Into #RtnValue (value)
Select Value = ltrim(rtrim(Substring(#List,1,Charindex(#SplitOn,#List)-1)))
Set #List = Substring(#List,Charindex(#SplitOn,#List)+len(#SplitOn),len(#List))
End
Insert Into #RtnValue (Value)
Select Value = ltrim(rtrim(#List))
Return
END
Your Proc
CREATE PROCEDURE testing
(
#stringVar NVARCHAR(255) = NULL
)
....
BEGIN
Select * from table
where column not IN(SELECT Value
FROM dbo.FnSplit(#stringVar,'~'))
.....
END
There is n't any built-in delimiter function in Sql Server. You can use user defined table value function for this purpose.
Create FUNCTION [dbo].[fnSplitString]
(#pString varchar(max),#pSplitChar char(1))
returns #tblTemp table (tid int,value varchar(1000))
as
begin
declare #vStartPosition int
declare #vSplitPosition int
declare #vSplitValue varchar(1000)
declare #vCounter int
set #vCounter=1
select #vStartPosition = 1,#vSplitPosition=0
set #vSplitPosition = charindex( #pSplitChar , #pString , #vStartPosition )
if (#vSplitPosition=0 and len(#pString) != 0)
begin
INSERT INTO #tblTemp
(
tid ,
value
)
VALUES
(
1 ,
#pString
)
return --------------------------------------------------------------->>
end
set #pString=#pString+#pSplitChar
while (#vSplitPosition > 0 )
begin
set #vSplitValue = substring( #pString , #vStartPosition , #vSplitPosition - #vStartPosition )
set #vSplitValue = ltrim(rtrim(#vSplitValue))
INSERT INTO #tblTemp
(
tid ,
value
)
VALUES
(
#vCounter ,
#vSplitValue
)
set #vCounter=#vCounter+1
set #vStartPosition = #vSplitPosition + 1
set #vSplitPosition = charindex( #pSplitChar , #pString , #vStartPosition )
end
return
end
There is no easy way of this. I would recomend reading this article.
You need to split your string progmaticly. There is no such function in sql.
There are many ways of implementing split functions in SQL Server, with lots of different performance characteristics: some (ab)use the XML functionality of SQL server, some use Tally tables, some use the CLR etc. For a description of one of these methods and a performance comparison, I'd recommend you'd look at Jeff Moden's article on SQL Server Central (registration required).
Once you have a table-valued splitter function available, you can implement your select simply:
select *
from MyTable t
where t.MyColumn not in (select Item from dbo.MySplit(#stringVar, '~') where Item is not null)
;
If it's just for testing existence then:
Select * from table where CHARINDEX('~'+column+'~' , '~'+#stringVar+'~' ,1)=0
I have made the following scalar valued function
CREATE FUNCTION [dbo].[CountCustomers]
(
#Name varchar
)
RETURNS int
AS
BEGIN
DECLARE #Result int
SET #Result = 1
RETURN #Result
END
But when I am calling it as
SELECT dbo.CountCustomers
I am not able to do it.
You defined a parameter for your function (#Name), so call the function with a value for that parameter:
SELECT dbo.CountCustomers('foo')
You need to pass a value into your function such as this:
SELECT dbo.CountCustomers('name')
The reason is you have #Name varchar as a parameter.
You can also call it like this:
DECLARE #Count INT
SET #Count = dbo.CountCustomers('name')
SELECT #Count
You need to add parentheses to call the function, and then add in one parameter in order for it to work.
SELECT dbo.CountCustomers('hello world')
Since a week am working with MYSQL , got to execute the Stored Procedure as well as Views but Facing some problem retrieving the values returned from a function.
Here's the Function:
CREATE DEFINER=`root`#`localhost` FUNCTION `GetProductIdsStringByEnquiryId`
(
InEnquiryId int
) RETURNS varchar(4000) CHARSET utf8
BEGIN
DECLARE InProductIds varchar(4000);
DECLARE ProductId varchar(50);
DECLARE x,y,z INT;
DECLARE sp1_cursor CURSOR FOR SELECT ProductId FROM enquiryproductid where
EnquiryId=InEnquiryId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET z = 1;
SET InProductIds='';
OPEN sp1_cursor;
REPEAT
FETCH sp1_cursor INTO ProductId;
SETInProductIds=concat(InProductIds,ProductId,',');
UNTIL (z=1)
END REPEAT;
CLOSE sp1_cursor;
RETURN InProductIds ;
END
I was initially working with SQL SERVER 2005, and the function which I have written in their I tried converting it as above in MYSQL,
Here's the SQL Function Code:
CREATE function [dbo].[GetBranchIdsStringByEmployeeId]
(
#EmployeeId as integer
)
returns nvarchar(4000)
as
begin
declare #BranchIds as nvarchar(4000)
set #BranchIds=''
if exists(select 1 from dbo.BranchEmployees where EmployeeId=#EmployeeId)
begin
select #BranchIds=#BranchIds+cast(BranchId as nvarchar(50))
+',' from dbo.BranchEmployees where EmployeeId=#EmployeeId
order by BranchId
end
return #BranchIds
end
Can anybody Please Let me know if the Function What I have written in MYSQL is in ProperManner or not? Please do help me out.
Thank You.
Not read fully through it, but few comments
Variable assignment in mysql uses := (in set #variable it is ok to use =, in select #variable:=#variable+1)
Are you trying to
SELECT group_concat(BranchId)
FROM dbo.BranchEmployees
WHERE EmployeeId = #EmployeeId
?