I have a function that is defined as:
Where XXXXX is my schema YYYYY is my package.
PROCEDURE "XXXXX"."YYYYY.SPATIAL::SP_GA_PT_PATH_DISTANCE" (IN PID NVarChar(36))
LANGUAGE SQLScript
SQL SECURITY INVOKER
--DEFAULT SCHEMA <default_schema_name>
AS
BEGIN
I want to call a function and assign the result to a variable, I have tried the following two ways:
intIntersect := XXXXX.YYYYY.SPATIAL::GA_INTERSECT (32.925148, -117.020051,
32.924672, -117.019454,
32.924488, -117.020322,
32.924849, -117.019759);
SELECT XXXXX.YYYYY.SPATIAL::GA_INTERSECT (32.925148, -117.020051,
32.924672, -117.019454,
32.924488, -117.020322,
32.924849, -117.019759) INTO intIntersect FROM DUMMY;
I have played with different permutations of this, but nothing works.
Any ideas?
Thanks.
What you describe as a FUNCTION is really a PROCEDURE in your code example.
These differ in the ways you can call either of them.
Procedures need to be called via the CALL statement.
Functions can either be used as scalar function in all places where you can use expressions (i.e. the projection list of a SELECT-statement) or, for table-typed functions, like a table in the WHERE condition.
The parameters handed over to the procedure seem to be a list of data items.
The general way to pass "lists" of parameters is to use a table-type parameter:
CREATE FUNCTION "XXXXX"."YYYYY.SPATIAL::SP_GA_PT_PATH_DISTANCE"
(IN_PIDS TABLE (PID NVARCHAR(36)) )
RETURNS TABLE (DISTANCES DECIMAL)
AS
BEGIN
SELECT * FROM :IN_PIDS;
...
ADO.NET is being used to access a MySQL database in my application. Some stored procedures were developed out of house. I applied them to the database. When trying to access a stored procedure in the database, the following exception occurs:
FUNCTION your_db.log_insertLogMessage does not exist
When calling this code:
MySqlCommand cmd = CreateCommand(procName, prams);
return cmd.ExecuteNonQuery();
The procName is string which is set correctly. Prams is MySqlParameter array. In the debugger, "?" appears for the array values, when expanding in Visual Studio.
The database seems to be accessed with no issue. I changed the database name to a dummy name and got a different error regarding the database not existing.
I removed all the stored procedures and received a new error saying a function or stored procedure with the given name did not exist.
I then reapplied the stored procedures, and I am now back to original error. The code for the stored procedure is:
CREATE DEFINER=`root`#`localhost` PROCEDURE `log_insertLogMessage`<br>
(IN `Name` varchar(100), IN `Description` varchar(5000), IN `Message` varchar(5000)
)
begin
INSERT INTO DBlog(UserName, Descr, LogMessage, WhenOccurred) values(Name, Description, Message, CURDATE());
end
I am able to call the stored procedure without issue in MySQL itself.
What am I missing?
I figured out the problem. I had to switch to an older verson mySql.data.dll. The database was set up correctly, and the code was fine. It was just a connector issue.
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
I'm using MySQL 5.5 (x64) and MySQL Workbench 5.2 deployed locally on a Windows 7 workstation for development purposes. I used MySQL Workbench to build a schema with the following function definition:
CREATE FUNCTION `db`.`get_public_name` (GPN_entID INT) RETURNS VARCHAR(64)
DETERMINISTIC
BEGIN
DECLARE GPN_pubName VARCHAR(64);
SELECT public_name INTO GPN_pubName
FROM entity WHERE id_entity=GPN_entID LIMIT 1;
RETURN GPN_pubName;
END
I then attempt to "Forward Engineer" the schema to the database with the following options specified:
DROP Objects Before Each Create Object
Generate DROP SCHEMA
Add SHOW WARNINGS After Every DDL Statement
GENERATE INSERT Statements for Tables
After this, MySQL Workbench attempts to publish to the server:
CREATE FUNCTION `db`.`get_public_name` (GPN_entID INT) RETURNS VARCHAR(64)
DETERMINISTIC
BEGIN
DECLARE GPN_pubName VARCHAR(64);
SELECT public_name FROM entity WHERE id_entity = GPN_entID;
RETURN GPN_pubName;
END
This results in the following error:
Executing SQL script in server
ERROR: Error 1415: Not allowed to return a result set from a function
Upon closer examination, I noticed the "INTO" and "LIMIT" clauses of the SELECT statement have been removed from the original function definition. This looks like it might be a cached version of the function, but I have tried everything I can think of (short of uninstalling and reinstalling MySQL Workbench) to flush any such cache to reload the correct version, but to no avail.
So, why is this change happening and how do I prevent it from happening?
Try changing to this:
SELECT public_name FROM entity WHERE id_entity = GPN_entID LIMIT 1 INTO GPN_pubName;
I'm embarrassed; if it wasn't for the fact this may be useful to others, I'd just go ahead and delete this question to hide my shame.
It turns out I created two functions with the same name and MySQL Workbench happily let me do so. I didn't notice that was the case until I started going through the stored routines with a more careful eye. I was editing one, but the other one (which had the error) was never changed. Since publishing each function involved dropping any earlier version from the database, I probably wouldn't have noticed this until things weren't working properly.
When I drag a particular stored procedure into the VS 2008 dbml designer, it shows up with Return Type set to "none", and it's read only so I can't change it. The designer code shows it as returning an int, and if I change that manually, it just gets undone on the next build.
But with another (nearly identical) stored procedure, I can change the return type just fine (from "Auto Generated Type" to what I want.)
I've run into this problem on two separate machines. Any idea what's going on?
Here's the stored procedure that works:
USE [studio]
GO
/****** Object: StoredProcedure [dbo].[GetCourseAnnouncements] Script Date: 05/29/2009 09:44:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAnnouncements]
#course int
AS
SELECT * FROM Announcements WHERE Announcements.course = #course
RETURN
And this one doesn't:
USE [studio]
GO
/****** Object: StoredProcedure [dbo].[GetCourseAssignments] Script Date: 05/29/2009 09:45:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAssignments]
#course int
AS
SELECT * FROM Assignments WHERE Assignments.course = #course ORDER BY date_due ASC
RETURN
I've also seen this problem several times and while I don't know what causes it, I've come across a pretty easy way to get past it. It involves manually editing the xml within the .dbml file, but it's a pretty simple edit.
Right-click on your Data Context's .dbml file in the Solution Explorer (not the .layout file nor the designer.cs file) and open it with the XML Editor. You should find your stored procedure listed in a <Function> ... </Function> block. You should also find the custom class you would like to set as the Return Type listed in a <Type> ... </Type> block.
Step one is to give your custom class an identifier. You do so by adding an "Id" tag, like this, making sure that it's unique within the dbml file:
<Type Name="MyCustomClass" Id="ID1">
Step two is to tell your function to use the newly ID'd type as the Return Type. You do so by replacing the line in your <Function> block that looks like
<Return Type="System.Int32" />
with
<ElementType IdRef="ID1" />
Save the file, exit, and rebuild. Done. Re-open the .dbml file in design mode to verify: Your procedure will now have the custom class set as the Return Type.
I had a similar mapping problem, but I found the culprit in my case.
If your procedure or any subprocedure that gets called has temporary objects like
CREATE TABLE #result (
ID INT,
Message VARCHAR(50)
)
then you're in trouble, even if you don't select anything of these temporaries.
The mapper has a general problem with these temporary objects, because the type can be changed outside the procedure in the session context. Temporary objetcs are not typesafe for the mapper and he refuses the usage os them.
Replace them by table variables and you're back in business
DECLARE #result AS TABLE (
ID INT,
Message VARCHAR(50)
)
I followed the link provided by Tony for a better solution (same answer as Arash's)
do read the blog, especially the last part, for there is a thing to consider when adding SET FMTONLY OFF in your stored procedure.
When you add
SET FMTONLY OFF
in the beginning of the stored procedure and load it to DBML,
LINQ2SQL would execute the actual stored procedure.
To get the correct return table object type,
said stored procedure must return something when called w/o parameter(s).
That means:
1. Have default value for all input parameters
2. Make sure SP returns at least a row of data -- this is where I stumbled
create table #test ( text varchar(50) );
insert into #test (text) values ('X'); -- w/o this line, return type would be Int32
select * from #test; -- SP returns something, proper object type would be generated
return;
Okay, I found the problem... kind of. I had changed the name of the table "Assignments" and forgot to update the stored procudure, so the DBML designer was confused. BUT even after I updated the stored procedure, deleted it from the DBML designer and readded it, it wasn't working!
This is nearly the same problem discussed here: http://forums.asp.net/t/1231821.aspx.
It only worked when I deleted the stored procedure from the database and recreated it, and deleted it from the DBML designer, recompiled, restarted Visual Studio, and added it again. This is the second time I've run into "refresh" problems with the Visual Studio DBML designer...
I managed to work out an easier way, which just wasn't obvious at the time, but sounds straight forward when written down:
Delete the stored procedure from the design surface of the .dbml file
Click Save All files
Click Refresh in Server Explorer on the list of Stored Procedures
Add (drag) the stored procedure back onto the design surface of the .dbml file
Click Save All
Click Build
Check the designer.cs code file and you will have the updated C# code for the new version of the stored procedure
check http://www.high-flying.co.uk/C-Sharp/linq-to-sql-can-t-update-dbml-file.html
I had the same problem, but only happens if my sp uses FTS, what i did was "cheat" the dbml designer, I remove the fts language stuff and works perfectly, now i can change the return type. Later i go to the sp and add the fts again and works pefectly!.
Hope this help.
The way to get around this issue is:
Add "set fmtonly off;" to the beginning of your stored procedure.
After adding that statement get DBML generate the code for your stored procedure.
If your stored procedure's return type is still 'int' in your DBML code, comment the entire code of stored procedure, create a new SELECT statement whose returning fields types and names match the original's SELECT statement and get DBML regenerate the code again. It has to work!
Thanks #Rubenz, I was also using FTS (Full-Text Search) in a stored procedure and your steps worked.
I commented the FTS section from the stored procedure, added the stored procedure to .dbml, and then uncommented the FTS section back to original.
This also happens when using sql user-defined types as parameters in stored procedures
http://alejandrobog.wordpress.com/2009/09/23/linq-to-sql-%e2%80%94-can%e2%80%99t-modify-return-type-of-stored-procedure/
Better solution found here: http://tonesdotnetblog.wordpress.com/2010/06/02/solution-my-generated-linq-to-sql-stored-procedure-returns-an-int-when-it-should-return-a-table/
OK, I didnt want to be changing anything in my Designer.cs code, I knew there was a different problem and it wasnt related to my stored procedure (I wasnt using temp table anyway).
Simply deleting the sp from the database and updating the model wasnt helping at all. New model created still had the same problems...
What I found is that for some reason a copies of my sp were created in DatabaseModel -> Function Imports.
What I did, I deleted the duplicated objects in Function Imports and updated the model. It worked!
Regards,
Chris
I realize that this is an old question but the above suggestions pointed me in the right direction but did not work in my case. I ended up editing the dbml file with the XML editor in Visual Studio as suggested above.
Once in the file, look for the Function section for the stored procedure. You will most likely not see the section – ElementType – which defines the return type. I began to edit the fields from another Function (stored procedure) and found that this was too tedious and may introduce issues.
I decided to delete all the Column definitions from the ElementType - but leave the ElementType section and save the file. I then deleted the stored procedure from the designer and re-added it. It then filled in the correct columns within the ElementType. Worked beautifully.