我有一个用SQL创建的函数,但出现此错误“ SQL服务器问题-创建函数必须是批处理中的唯一语句”。我检查了其他类似的主题,但找不到任何错误。我正在使用SQL Server 2012
CREATE FUNCTION GETLLPATH(@objectid FLOAT)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @dir VARCHAR(MAX);
DECLARE @obj_id FLOAT;
DECLARE Name_Cursor CURSOR LOCAL FOR
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A
WHERE A.DataID = @obj_id;
DECLARE
SET @dir = NULL;
SET @obj_id = @objectid;
WHILE 1=1 BEGIN
OPEN Name_Cursor;
FETCH Name_Cursor INTO @name;
IF @@FETCH_STATUS <> 0 BREAK or @name_NAME = 'Enterprise';
IF @dir IS NOT NULL BEGIN
SET @dir = (ISNULL(@name_NAME, '') + ':' + isnull(@dir, '')) ;
END
IF @dir IS NULL BEGIN
SET @dir = @name_NAME;
END
SET @obj_id = @name_PARENTID;
CLOSE Name_Cursor;
DEALLOCATE Name_Cursor;
END;
return(@dir);
END;
GO
由于“必须声明标量变量”,我也遇到了变量错误,最后又出现了一个错误-“期望对话”,请您帮忙。
答案 0 :(得分:2)
我相信您只是有一些错误的代码。
尝试一下:
CREATE FUNCTION GETLLPATH(
@objectid FLOAT
)
RETURNS VARCHAR(4000)
AS
BEGIN
DECLARE @dir VARCHAR(MAX);
DECLARE
@obj_id FLOAT
, @name_NAME VARCHAR(50) -- or whatever your field size is.
, @name_PARENTID VARCHAR(50) -- again, whatever your field size is.
DECLARE Name_Cursor CURSOR LOCAL FOR
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A WHERE A.DataID = @obj_id;
SET @dir = NULL; -- redundant.
SET @obj_id = @objectid; -- this can be set at declaration ( e.g. DELARE @obj_id FLOAT = @obj_id ).
WHILE ( 1 = 1 ) BEGIN
OPEN Name_Cursor;
FETCH Name_Cursor INTO @name;
IF ( @@FETCH_STATUS <> 0 OR @name_NAME = 'Enterprise' )
BREAK;
IF ( @dir IS NOT NULL ) BEGIN
SET @dir = (ISNULL(@name_NAME, '') + ':' + isnull(@dir, '')) ;
END
IF @dir IS NULL BEGIN
SET @dir = @name_NAME;
END
SET @obj_id = @name_PARENTID;
CLOSE Name_Cursor;
DEALLOCATE Name_Cursor;
END
RETURN @dir;
END
GO
就个人而言,我从不不喜欢使用WHILE(1 = 1)。您保证有出口吗?
此外,我强烈建议您使用游标的替代方法。也许使用TABLE变量并像这样循环遍历:
CREATE FUNCTION GETLLPATH(
@objectid FLOAT
)
RETURNS VARCHAR(4000)
AS
BEGIN
-- declare variables --
DECLARE @id INT
, @dir VARCHAR(MAX)
, @obj_id FLOAT = @objectid
, @name_NAME VARCHAR(50)
, @name_PARENTID VARCHAR(50)
-- declare table variable --
DECLARE @data TABLE( [name] VARCHAR(50), [parent_id] VARCHAR(50), [id] INT IDENTITY (1,1) );
-- insert data --
INSERT INTO @data ( [name], [parent_id] )
SELECT A.Name, A.ParentID FROM OTCS_User.DTree A WHERE A.DataID = @obj_id;
-- for-each row... --
SET @id = 1;
WHILE ( @id <= ( SELECT MAX( id ) FROM @data ) )
BEGIN
-- current row --
SELECT
@name_NAME = [name]
, @name_PARENTID = [parent_id]
FROM @data WHERE [id] = @id;
-- do your work here...
-- next row --
SET @id = ( @id + 1 );
END
RETURN @dir;
END
GO
答案 1 :(得分:0)
即使在测试您的查询之前,也存在一些语法错误:
在没有变量名的情况下,单词“ DECLARE”不应出现在中间, @name_Name和@name_PARENTID未声明
DECLARE @name_NAME varchar,@ name_PARENTID int
(根据源表检查变量类型)
如果@@ FETCH_STATUS <> 0 BREAK或@name_NAME ='Enterprise'不正确
IF @@ FETCH_STATUS <> 0或@name_NAME ='Enterprise' BREAK
“ Create Function必须是批处理中唯一的语句”-通常 表示存在语法错误。
答案 2 :(得分:0)
说实话,这是一个总的猜测,(最重要的是)未经测试;由于缺少样本数据和预期结果。
无论如何,就像我在评论中说的那样,CURSOR
和标量值函数在这里确实表现不佳。如果您只是想用冒号(:
)分隔数据,则可以使用STUFF
和FOR XML PATH
。
就像我说的那样,这是未经测试的完成,但可能会让您走上正确的路:
CREATE FUNCTION dbo.GetllPath (@objectID int) --Is it really a float? I've used an int
RETURNS table
AS RETURN
SELECT STUFF((SELECT ':' + DT.[Name]
FROM OTCS_User.DTree DT
WHERE DT.DataID = @obj_id
--ORDER BY SOMETHING HERE!!!
FOR XML PATH('')),1,1,'') AS llPath;
GO