Setting SCHEMABINDING and IsDeterministic for a CLR function - sqlclr

I have an existing C# CLR runtime function that I am using with SQL Server 2012. I would like to set the IsDeterministic and SCHEMABINDING options on this function so I can use it for persisting a computed column in a table.
Here is the alter statement:
ALTER FUNCTION [dbo].[authorityFromURI](#URI [nvarchar](4000))
RETURNS [nvarchar](4000) WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [KDPSqlServerProject].[UserDefinedFunctions].[authorityFromURI]
How should this alter statement be modified to set these options?

You have to set the IsDeterminstic property within the function code itself, e.g
[SqlFunction(IsDeterministic = true, IsPrecise = true [...])]
To make it schemabinding:
RETURNS NVARCHAR(4000)
WITH SCHEMABINDING, EXECUTE AS CALLER
That said, I haven't tested these options together with persistence...

Related

MySQL Function Characteristic

I want to create a function that basically returns a random string. I don't know what characteristics to assign in this situation. I'm also in an environment that uses binary logging.
Here's a simplified version of my function:
CREATE FUNCTION `MYRAND`() RETURNS char(10) NOT DETERMINISTIC
RETURN CONCAT('rand_', FLOOR(RAND() * 10000));
I get this error when creating the function in my environment.
This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in
its declaration and binary logging is enabled (you might want to use
the less safe log_bin_trust_function_creators variable)
Possible characteristics:
NOT DETERMINISTIC - used because this function returns random values
READS/MODIFIES SQL DATA - Function does not read data from tables
NO SQL - I am calling other SQL functions (RAND) so I'm not sure if I should be specifying this or not...
Any advice on how to properly define this function when binary logging is enabled would be appreciated.
MySQL wants you to declare the function as DETERMINISTIC, NO SQL, or READS SQL DATA.
Is it DETERMINISTIC? No - Since it is random.
Does id read SQL DATA? No - Since you have no SELECT statement.
Does it modify SQL DATA? No - Since you have no INSERT, UPDATE or DELETE statement.
Since your function does not touch any data in the DB it's NO SQL.
So you should declare it as NOT DETERMINISTIC and NO SQL
CREATE FUNCTION `MYRAND`() RETURNS char(10) NOT DETERMINISTIC NO SQL
RETURN CONCAT('rand_', FLOOR(RAND() * 10000));
Use somthing like this code:
CREATE FUNCTION get_string(in_strlen int) RETURNS VARCHAR(500) DETERMINISTIC
BEGIN
set #var:='';
while(in_strlen>0) do
set #var:=concat(#var,IFNULL(ELT(1+FLOOR(RAND() * 1000),1,2,3,4,5,6,7,8,9));
set in_strlen:=in_strlen-1;
end while;
RETURN #var;
END

Strange error message: "Must declare the scalar variable" when pass TVP parameters into table-valued function

I have a simple custom type for use it as table valued parameter.
Like this:
CREATE TYPE dbo.PeriodsList AS TABLE
(
PeriodDate NVARCHAR(8) NOT NULL
)
I also have very simple table valued function:
alter FUNCTION GetPeriodsInYear (#periods dbo.PeriodsList READONLY) returns #PeriodsSet Table(period NVARCHAR(8))
BEGIN
insert #PeriodsSet
select
'0' as period
Return
end
But when I try to execute this function in this way
DECLARE #periods1 dbo.PeriodsList
INSERT INTO #periods1
VALUES ('20130916')
select * from GetPurchasesInYear(#periods1)
I receive error message - "Must declare the scalar variable "#periods1".
I have found many examples about stored procedures but not about functions. Is it possible to pass table valued parameters into functions?
And where the mistake in my code?
Check the "compatibility level" of your SQL Server 2008 database. If it's set to 80 (SQL Server 2000), you will get the error you are describing when you try to call a function (but not a stored procedure) that takes a table-valued parameter.
It should work if the compatibility level value is 90 (SQL Server 2005) or higher.
To view the compatibility level of your database, do:
SELECT compatibility_level
FROM sys.databases
WHERE name = 'YOUR_DB_NAME_HERE';
Source: http://msgroups.net/microsoft.public.sqlserver.programming/pass-table-valued-para/97879
Changing the compatibility level (SQL Server 2008): http://technet.microsoft.com/en-us/library/bb510680%28v=sql.100%29.aspx

Temporary tables and table-valued parameters in SQL Server

I have a procedure that receives a table as a parameter. I need to fill it on then return it to another procedure that executes the first one. But, the problem is that when y compile I receive this error message:
Mens 352, Nivel 15, Estado 1, Procedimiento Person_InsertCloud, LĂ­nea 1
The table-valued parameter "#TableServerIds" must be declared with the READONLY option.
Can't a table as a parameter can be modified? What other options do I have?
Thanks
No the contents of the TVP can't be modified. Upvote Relax restriction that table parameters must be readonly when SPs call each other if you want this functionality.
The other option is a local #temp table. Stored procedures have read and write access to #temp tables created in parent scopes. But this does mean that callers of the sub procedure need to be aware of this requirement and create the expected #temp table before calling.
An example below
CREATE PROC P1
AS
CREATE TABLE #Foo
(
X VARCHAR(50)
);
EXEC P2;
SELECT *
FROM #Foo;
GO
CREATE PROC P2
AS
IF OBJECT_ID('tempdb..#Foo') IS NULL
BEGIN
RAISERROR ('This procedure expects table #Foo to already exist',16,1);
RETURN;
END
INSERT INTO #Foo
VALUES ('Inserted by P2')
GO
EXEC P1
Can't a Table as a parameter can be modified?
No. It is one of the restrictions on TVPs.
The restriction is documented:
Table-valued parameters must be passed as input READONLY parameters to Transact-SQL routines. You cannot perform DML operations such as UPDATE, DELETE, or INSERT on a table-valued parameter in the body of a routine.
Instead of filling a table, you can return a table from your second stored procedure using SELECT.

SQL alter recursive function

I'm using SQL Server 2008.
I want to execute an ALTER on a recursive function. The alter adds parameters, it seems to choke on that.
The function has no dependencies so I can safely do a DROP+CREATE, but what should be done when the function does have dependencies?
The error message is this one
Msg 8144, Level 16, State 2, Server TESTSERVER, Procedure fn_IsOwnerFunction, Line 177
Procedure or function dbo.fn_IsOwnerFunction has too many arguments specified.
The message appears a few more times, each time for a line where the function refers to itself. Note: it refers to its new version that has more parameters. After DROP+CREATE, the ALTER script works without errors.
It is ok to drop a function that is used from other functions or stored procedures.
Of course, after you drop/create the function you need to alter the functions and stored procedures that uses the function to add the new parameters.
If the error is "too many arguments specified" then your calling code is passing in too many parameters. This could mean that the ALTER FUNCTION statement you ran earlier didn't actually process fully. That could be because of a syntax error or something similar. Run the Alter statement again and check the error message there.
EDIT:
Add a DROP FUNCTION statement before your CREATE FUNCTION statement:
if exists (select * from information_schema.routines Where routine_name = 'udf_FunctionName')
drop function udf_FunctionName
GO
CREATE FUNCTION [dbo].[udf_FunctionName]
...

Mapping UDF using LINQ-to-SQL Designer

I'm trying to add a new table-valued udf to an existing LINQ-to-SQL designer in VS 2008. Everything goes fine and there are no compile errors or warnings; however when I try to execute the method I get the following error:
System.InvalidOperationException: The method is not mapped as a stored procedure or user-defined function...
I've checked the connection string, made sure the udf exists in the target database, and successfully queried another udf that was added previously. The Function attribute is present in the generated designer code. I've deleted the file and recreated it from scratch with the same results. I've successfully added udfs before and am baffled by this turn of events.
Have I missed something?
EDIT:
Here's the function:
ALTER FUNCTION [dbo].[GetIndividualInfoByName]
(
#Name varchar(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT
Id
,Ssn
,FamilyName
,MiddleName
,GivenName
,Suffix
,Street1
,Street2
,Street3
,City
,[State]
,PostalCode
,Country
FROM
Delta.dbo.IndividualInfo
WHERE
GivenName LIKE #Name Or FamilyName LIKE #Name
)