I was wondering why this simple sql function won't work?
CREATE FUNCTION dbo.getTableCounts (#STREAM_ID nvarchar(10))
RETURNS table
AS RETURN ( select 1 as 'one', 2 as 'two');
When I run it in qwerybuilder I get two error messages:
Incorrect syntax near the keyword 'table' (for line 2)
and
Incorrect syntax near ',' (for line 3)
I don't understand how this is incorrect syntax. Does anyone see why this is an error?
According to ASE's Reference manual You can only return a scalar expression:
create function [ owner_name. ] function_name
[ ( #parameter_name [as] parameter_datatype [ = default ]
[ ,...n ] ) ]
returns return_datatype
[ with recompile]
as
[begin]
function_body
return scalar_expression
[end]
So you can't use table as data type.
Unlike Microsoft SQL Server, in Sybase if you need table as a result type you don't use a function but a stored procedure. In your case the definition of the procedure (written in Watcom-SQL) will look like:
CREATE PROCEDURE getTableCounts(#STREAM_ID NVARCHAR(10))
RESULT(one INT, two INT)
BEGIN
SELECT 1 AS one, 2 AS two;
END;
However this option is not supported by Transact-SQL dialect in Sybase.
Related
In SQL Server, if I have a scalar-value function that takes a table-valued parameter argument, defined as follows (simplified example):
CREATE TYPE IntTableType AS TABLE(Value INT);
CREATE FUNCTION dbo.MeetsCustomRequirements
(
#TypeIDs IntTableType READONLY
)
RETURNS TINYINT AS
BEGIN
-- (Function logic here; returns either 0 or 1 based on the specified #TypeIDs values)
END
I'd like to be able to call that function from a view, where the table-valued parameter of the view is generated from an inline query, like:
CREATE VIEW dbo.vEligibleItems AS
SELECT i.ItemID
FROM tItems i
WHERE dbo.MeetsCustomRequirements (
(SELECT TypeID FROM tItemTypes WHERE ItemID = i.ItemID)
);
However, this doesn't work because the result of that nested SELECT query isn't an IntTableType (even though it is a list of INT values). (Specific error generated is Error 206: Operand type clash: int is incompatible with IntTableType.)
My two-part question: Is there a way to call a function taking a table-valued parameter argument from a view? If not, what alternative approaches are available to accomplish the same thing?
Database is SQL Server 2008.
(Bringing the logic in the function inline in the view is not ideal because the function is called from several different places, not just from this one view.)
I don't think it is possible with VIEW
CREATE VIEW [ schema_name . ] view_name [ (column [ ,...n ] ) ]
[ WITH [ ,...n ] ]
AS select_statement
[ WITH CHECK OPTION ]
[ ; ]
With view syntax maximum you can get is CTE. To pass TVP-argument you need to declare it somewhere, but you can't do it inside view definition.
Very ugly solution just concept not actual code (using XML to pass multiple values to helper function):
CREATE VIEW dbo.vEligibleItems
AS
WITH cte (view.*, XML_with_all_types_id) AS
(
SELECT *,
[XML_with_all_types_id] = magic_here(
SELECT iTypeID FROM tItemTypes t WHERE WHERE t.ItemID = i.ItemID)
FROM tItems i
)
SELECT *
FROM cte
WHERE dbo.MeetsCustomRequirements_helper(XML_with_all_types_id) = 1
CREATE FUNCTION dbo.MeetsCustomRequirements_helper(#xml XML)
RETURNS INT
AS
(
// unwrap xml to TVP
DECLARE #tvp your_tvp_type;
INSERT INTO #tvp(cols)
SELECT *
FROM #xml.node(...);
DECLARE #result = dbo.MeetsCustomRequirements(#tvp);
RETURN #result
)
Can you just change your View to Table-Valued User-Defined Function and cover its with view if needed like (I know performance will be poor):
CREATE VIEW name
AS
SELECT *
FROM dbo.fn_getdata();
CREATE FUNCTION dbo.fn_getdata()
RETURNS #result TABLE
AS
BEGIN
/* multi-statement you can declare your TVP */
END
I want to create a function in SQL Server 2005 that returns a table which the query is passing from my program...
But when I create that function with this script:
CREATE FUNCTION fn_test (#source varchar(255))
RETURNS TABLE AS
RETURN
EXECUTE (#source)
The script is showing error message
Incorrect syntax near the keyword "EXECUTE`
It's perfectly correct - you're not allowed to execute arbitrary SQL as part of an inline table valued function:
--Transact-SQL Inline Table-Valued Function Syntax
CREATE FUNCTION [ schema_name. ] function_name
( [ { #parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [ READONLY ] }
[ ,...n ]
]
)
RETURNS TABLE
[ WITH <function_option> [ ,...n ] ]
[ AS ]
RETURN [ ( ] select_stmt [ ) ]
[ ; ]
If you need(*) to have a facility to pass arbitrary SQL into a SQL Server object and have it execute it, use a stored procedure rather than a function. Functions are not meant to alter the state of the database, but arbitrary SQL can do... arbitrary things.
(*)You don't.
As a procedure, it would be:
CREATE PROCEDURE test (#source varchar(255))
AS
EXECUTE (#source)
But as is probably evident at this point - if you want to execute arbitrary SQL stored as strings, you may as well just directly call EXECUTE on them. That's part of what I was alluding to when I put my (*) in. The other part is - why send it in a string variable to the server at all - why not just send the SQL you want to execute, if you're going to run arbitrary SQL on the server anyway.
I've created a table valued function:
CREATE FUNCTION TestFunction
(
#username VARCHAR(80)
)
RETURNS TABLE
AS
RETURN
(
SELECT 0 AS TestValue
)
Then try to call it as so:
SELECT TestValue
FROM dbo.TestFunction(SYSTEM_USER)
but get the error:
Incorrect syntax near the keyword 'SYSTEM_USER'
I've even tried making this a table valued function which is not inline, but I get the same error.
Am I missing something? Why am I getting this error?
On my 2k8 server I can only reproduce that with SQL Server 2000 (80) Compatibility level set, check the level of your 2005 database.
Meantime you can;
declare #su varchar(30) = SYSTEM_USER
select * from dbo.TestFunction(#su)
Here is the create statement:
create table dbmonitor.DBMON_DATABASE_TYPE (
DATABASE_TYPE_ID BIGINT IDENTITY NOT NULL,
DispName NVARCHAR(255) null,
primary key (DATABASE_TYPE_ID)
)
and this is the error I get:
13:40:57,685 ERROR [TestRunnerThread] SchemaExport [(null)]- The table name is not valid. [ Token line number (if known) = 1,Token line offset (if known) = 24,Table name = DBMON_DATABASE_TYPE ]
The table name is not valid. [ Token line number (if known) = 1,Token line offset (if known) = 24,Table name = DBMON_DATABASE_TYPE ]
Possibilities:
Is dbmonitor the name of your database? You can't put a . in a table name.
Do you mean CREATE TABLE dbmonitor.dbo.DBMON_DATABASE_TYPE?
Did you try CREATE TABLE DBMON_DATABASE_TYPE?
I'm not sure if dbmonitor is meant to be a schema name, but according to the documentation for the SQL CE CREATE TABLE statement, you cannot include a schema name with the table name.
Contrast this for SQL Server 2005 Compact Edition (just showing the initial part of the statement),
CREATE TABLE table_name
( { < column_definition > | < table_constraint > } [ ,...n ]
)
with this for SQL Server 2008:
CREATE TABLE
[ database_name . [ schema_name ] . | schema_name . ] table_name
This may not be exactly an answer for this question's criteria , but for those who might get here :
this error can also happen when you try to use EntityFramework.Extended library with Sql Server CE. It seems that they are not compatible.
check these links :
https://github.com/loresoft/EntityFramework.Extended/issues/35
https://github.com/loresoft/EntityFramework.Extended/issues/11
I'm using table values for the first time as a parameter to a function in SQL Server 2008. The code below produces this error:
Must declare the scalar variable "#RESULT".
Why?! I'm declaring it on the first line of the function!
ALTER FUNCTION f_Get_Total_Amount_Due(
#CUSTOMER_LIST [tpCSFM_CUSTOMER_SET_FOR_MONEY] READONLY
)
RETURNS [tpCSFM_CUSTOMER_SET_FOR_MONEY]
AS
BEGIN
--Prepare the return value, start with initial customer list
DECLARE #RESULT AS [tpCSFM_CUSTOMER_SET_FOR_MONEY]
INSERT INTO #RESULT SELECT * FROM #CUSTOMER_LIST
--Todo: populate with real values
UPDATE #RESULT SET tpCSAM_MONEY_VALUE = 100
--return total amounts as currency
RETURN #RESULT
END
Your declaration would fall into the 'Multi-statement table valued function' case:
Multistatement Table-valued Functions
CREATE FUNCTION [ schema_name. ] function_name
( [ { #parameter_name [ AS ] [ type_schema_name. ] parameter_data_type
[ = default ] [READONLY] }
[ ,...n ]
]
)
RETURNS #return_variable TABLE <table_type_definition>
[ WITH <function_option> [ ,...n ] ]
[ AS ]
BEGIN
function_body
RETURN
END
[ ; ]
Unfortunately the #return_variable cannot be declared as a table type, you'd have to copy the declaration of the TVP type into the function return table type.
This one compiles fine:
--Returns the name of the field to use to find results
ALTER FUNCTION f_Get_Total_Amount_Due(
#CUSTOMER_LIST [tpCSFM_CUSTOMER_SET_FOR_MONEY] READONLY
)
RETURNS #RESULT TABLE(
tpCSFM_CUS_ID uniqueidentifier PRIMARY KEY,
tpCSFM_MONEY_VALUE MONEY NULL
)
AS
BEGIN
--Prepare the return value, start with initial customer list
INSERT INTO #RESULT SELECT * FROM #CUSTOMER_LIST
--Todo: populate with real values
UPDATE #RESULT SET tpCSFM_MONEY_VALUE = 100
--return total amounts as currency
RETURN
END
I don't believe the table-valued functions got any new features for the return value to be able to be a user-defined table type.
However, you can try: RETURNS #RESULT [tpCSFM_CUSTOMER_SET_FOR_MONEY] and remove your separate DECLARE.
I'll need to check it out when I get a chance to set up a test case.