3

我有 3 个表,我必须检查祖父表 id 是否有孙表中的记录。如果是,则返回是,否则返回否。这是我的存储过程。我收到了不正确的语法错误。我是存储过程的新手。请帮我。

CREATE PROCEDURE P_Check
   @PKG_ID INT,
   @S_ID INT,
   @FLAG VCHAR(10) OUT

   DECLARE IDS CURSOR LOCAL FOR SELECT S_ID FROM T1 WHERE P_ID = @PKG_ID
   OPEN IDS
   FETCH NEXT FROM IDS into @S_ID

   WHILE @@FETCH_STATUS = 0
   BEGIN
      SELECT * FROM T2 WHERE S_ID = @S_ID

      IF @@ROWCOUNT<>0
         @FLAG = 'YES'
         RETURN 
      ELSE
         @FLAG = 'NO'

      FETCH NEXT FROM IDS into @S_ID
   END

   CLOSE IDS
   DEALLOCATE IDS
4

2 回答 2

4

需要检查的几件事:

  1. 我认为vcharSQL Server 中没有数据类型,除非那是您的自定义类型。所以改成varchar
  2. 你忘了AS
  3. 您可能希望将您的逻辑包含if在两者begin之间end

您可以编译的代码:

CREATE PROCEDURE P_Check
    @PKG_ID INT,
    @S_ID INT,
    @FLAG VARCHAR(10) OUT
AS
    DECLARE IDS CURSOR LOCAL FOR SELECT S_ID FROM T1 WHERE P_ID = @PKG_ID
    OPEN IDS
    FETCH NEXT FROM IDS into @S_ID
    WHILE @@FETCH_STATUS = 0

    BEGIN
      SELECT * FROM T2 WHERE S_ID = @S_ID
      IF @@ROWCOUNT<>0
      BEGIN
         SET @FLAG = 'YES'
         RETURN 
      END
      ELSE
      BEGIN
         SET @FLAG = 'NO'
         FETCH NEXT FROM IDS into @S_ID
      END
    END

    CLOSE IDS
    DEALLOCATE IDS

但是,我认为您的光标不会在您返回此处时关闭IF @@ROWCOUNT<>0。我认为你应该做的是改变这个:

IF @@ROWCOUNT<>0
BEGIN
    SET @FLAG = 'YES'
    RETURN 
END

对此:

IF @@ROWCOUNT<>0
BEGIN
    SET @FLAG = 'YES'
    GOTO ON_EXIT
END

然后像这样结束你的程序:

ON_EXIT:
    CLOSE IDS
    DEALLOCATE IDS    

然后在评论中回答你的问题,你已经在某种意义上“回归”了它。您可以像这样调用和测试您的程序:

declare @result varchar(10)
exec P_Check 1, 1, @result out
print @result
于 2013-04-11T03:05:54.443 回答
3

这太复杂了,在这里完全不需要也完全没有必要使用光标。

将您的程序简化为:

CREATE PROCEDURE P_Check
   @PKG_ID INT,
   @S_ID INT,
   @FLAG CHAR(1) OUT
AS BEGIN
   IF EXISTS (SELECT * FROM T2 
              INNER JOIN T1 ON T2.S_ID = T1.S_ID WHERE P_ID = @PKG_ID)
      SET @FLAG = 'Y'
   ELSE
      SET @FLAG = 'N'
END

认真使用 SQL Server 时,您需要摆脱使用游标和循环的逐行、痛苦的程序化思维,并且需要开始以集合方式思考以提高效率和生产力。

于 2013-04-11T05:01:38.913 回答