SQL Server用户定义的游标

时间:2016-11-03 17:11:05

标签: sql sql-server sql-server-2008

我正在尝试创建用户定义的游标,但是我收到以下错误,

Msg 102,Level 15,State 1,Line 25 &#39 ;;'附近的语法不正确。

我正在使用AdventureWorks2008r2

这是我的代码;

USE AdventureWorks2008r2
GO

DECLARE
    -- LOCAL VARIABLEs
    @OrderId INT,
    @status TINYINT

--declare the cursor 
DECLARE mynamelist CURSOR STATIC
FOR
SELECT Sales.SalesOrderHeader.SalesOrderID, Sales.SalesOrderHeader.STATUS
FROM Sales.SalesOrderHeader;

OPEN mynamelist;

FETCH NEXT
FROM mynamelist
INTO @status,
    @OrderId

WHILE @@FETCH_STATUS = 0
    IF @status = 1
    BEGIN
        FETCH NEXT
        FROM mynamelist
        INTO @status,@OrderId

        PRINT 'Order Number:' + CAST(@OrderId AS VARCHAR(10)) + 'Status:Approved';
    END;
    ELSE IF @status = 3
        PRINT 'Order Number:' + CAST(@OrderId AS VARCHAR(10)) + 'Status:Backordered';
    ELSE IF @status = 4
        PRINT 'Order Number:' + CAST(@OrderId AS VARCHAR(10)) + 'Status:Rejected';
    ELSE IF @status = 5
        PRINT 'Order Number:' + CAST(@OrderId AS VARCHAR(10)) + 'Status:Shipped';
    ELSE
        PRINT 'Order Number:' + CAST(@OrderId AS VARCHAR(10)) + 'Status:Cancelled';
    END;

CLOSE nynamelist;

DEALLOCATE mynamelist;

如何解决此错误

1 个答案:

答案 0 :(得分:1)

所以你有一些语法问题,然后是你的代码编写方式的一些逻辑问题。您将FETCH NEXT嵌套在IF语句中,因此WHILE块实际上不会选择下一条记录,除非@status = 1 ....

使用缩进和空格组织代码将有助于您大大了解步骤的逻辑和优先级。你错过了游标循环的BEGIN

另请注意,对于sql-server的分号并不总是必要的,除非在THROW和Common Table Expressions的情况下,之前的语句必须以分号结束,这就是为什么你经常看到它们被写为;WITH cte as和;THROW 51000, ...我确信还有其他一些例子我只是给了一些。

无论如何,转储所有的If如果使用case expression这个类型的操作更适合构建你的字符串然后打印它。

另请注意,如果结果中出现语法错误,您可以双击它,它会引发您遇到的语法错误。

DECLARE

-- LOCAL VARIABLEs
@OrderId INT , @status TINYINT


--declare the cursor 
DECLARE mynamelist CURSOR STATIC FOR
    SELECT
       h.SalesOrderID,
       h.Status
    FROM
       Sales.SalesOrderHeader h

open mynamelist; 

FETCH NEXT FROM mynamelist INTO @status, @OrderId

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE @Message NVARCHAR(1000)
    SET @Message = 'Order Number:' + CAST(@OrderId as VARCHAR(10)) + 'Status:'
    SET @Message = @Message + CASE
          WHEN @status = 1 THEN 'Approved'
          WHEN @status = 3 THEN 'Backordered'
          WHEN @status = 4 THEN 'Rejected'
          WHEN @status = 5 THEN 'Shipped'
          ELSE 'Cancelled'
       END

    PRINT @Message;

    FETCH NEXT FROM mynamelist INTO @status, @OrderId

END

CLOSE nynamelist;

DEALLOCATE mynamelist;