SQL Server问题-Create Function必须是批处理中的唯一语句

时间:2018-08-07 11:11:52

标签: sql sql-server sql-server-2012

我有一个用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

由于“必须声明标量变量”,我也遇到了变量错误,最后又出现了一个错误-“期望对话”,请您帮忙。

3 个答案:

答案 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)

即使在测试您的查询之前,也存在一些语法错误:

  1. 在没有变量名的情况下,单词“ DECLARE”不应出现在中间, @name_Name和@name_PARENTID未声明

    DECLARE @name_NAME varchar,@ name_PARENTID int

(根据源表检查变量类型)

  1. 如果@@ FETCH_STATUS <> 0 BREAK或@name_NAME ='Enterprise'不正确

    IF @@ FETCH_STATUS <> 0或@name_NAME ='Enterprise'      BREAK

  

“ Create Function必须是批处理中唯一的语句”-通常   表示存在语法错误。

答案 2 :(得分:0)

说实话,这是一个总的猜测,(最重要的是)未经测试;由于缺少样本数据和预期结果。

无论如何,就像我在评论中说的那样,CURSOR和标量值函数在这里确实表现不佳。如果您只是想用冒号(:)分隔数据,则可以使用STUFFFOR 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