我的PL / SQL程序有什么问题?

时间:2014-05-11 16:00:18

标签: oracle plsql

我建立了一个Oracle数据库(版本9.2,我知道它已经过时,但它是我大学安装的版本,我没有选择),包含用户列表和他们的直接朋友。我正在研究一组查询来列出"网络"一个用户,包括他的朋友'朋友,并计算有问题的用户和其他成员之间的分离程度。

我分别测试了这三个查询,并确认它们确实有效。

我现在想要创建一个PL / SQL过程来组合3个查询,以便能够将播放器的ID作为参数提供,还可以使用一个Execute语句启动三个查询。

但是,我无法运行该程序。我甚至无法转换过程中的第一个查询(请参阅下面的代码)。

有人可以解释一下我做错了吗?

以下是查询(它们正在运行):

INSERT INTO UserFriendsCopy
SELECT *
FROM UserFriends
WHERE PlayerID < FriendsWith;

INSERT INTO Degrees_Separation
   SELECT PlayerID, FriendsWith, LEVEL AS Degree
      FROM UserFriendsCopy
      START WITH PlayerID = 1
      CONNECT BY PRIOR FriendsWith = PlayerID;

SELECT FriendsWith, MIN(Degree)
FROM Degrees_Separation
GROUP BY FriendsWith;

这是我编写的替换第一个查询的过程。它不起作用。为什么呢?

CREATE OR REPLACE PROCEDURE procDegrees1
AS
DECLARE
    CURSOR UserFriendsNoDupl IS SELECT * FROM UserFriends WHERE PlayerID < FriendsWith;
BEGIN
    FOR record IN UserFriendsNoDupl
LOOP
    EXIT WHEN UserFriendsNoDupl%NOTFOUND;
    INSERT INTO UserFriendsCopy VALUES(record.PlayerID, record.FriendsWith);
END LOOP;
END;/

EXECUTE procDegrees1/

[更新]我已重新编写以下程序,以考虑到目前为止收到的意见。不过,它不起作用。

CREATE OR REPLACE PROCEDURE procDegrees1
AS
BEGIN
FOR record IN (SELECT * FROM UserFriends WHERE PlayerID < FriendsWith)
LOOP
    INSERT INTO UserFriendsCopy(PlayerID,FriendsWith) VALUES(record.PlayerID, record.FriendsWith);
END LOOP;
END;/

顺便说一句,这里是表定义,以及一些虚拟记录:

DROP TABLE Degrees_Separation;
DROP TABLE UserFriends;
DROP TABLE UserFriendsCopy;

CREATE TABLE UserFriends (
    PlayerID INT NOT NULL,
    FriendsWith INT NOT NULL,
    CONSTRAINT pkUserFriends
        PRIMARY KEY (PlayerID, FriendsWith),
    CONSTRAINT fkPlayerIDThird
        FOREIGN KEY (PlayerID)
        REFERENCES Player (PlayerID),
    CONSTRAINT fkPlayerIDFourth
        FOREIGN KEY (FriendsWith)
        REFERENCES Player (PlayerID)
);

CREATE TABLE UserFriendsCopy (
    PlayerID INT NOT NULL,
    FriendsWith INT NOT NULL,
    CONSTRAINT pkUserFriendsBis
        PRIMARY KEY (PlayerID, FriendsWith)
);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (1, 2);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (2, 1);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (2, 3);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (3, 2);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (2, 4);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (4, 2);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (1, 4);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (4, 1);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (5, 6);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (6, 5);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (3, 8);

INSERT INTO UserFriends (PlayerID, FriendsWith)
VALUES (8, 3);


CREATE TABLE Degrees_Separation (
    PlayerID INT NOT NULL,
    FriendsWith INT NOT NULL,
    Degree INT NOT NULL,
    CONSTRAINT fkPlayerIDSeventh
        FOREIGN KEY (PlayerID)
        REFERENCES Player (PlayerID),
    CONSTRAINT fkPlayerIDEighth
        FOREIGN KEY (FriendsWith)
        REFERENCES Player (PlayerID)
);

谢谢,LC

1 个答案:

答案 0 :(得分:2)

SQL*Plus reference says

  

SQL * Plus以与SQL命令相同的方式处理PL / SQL子程序,除了分号(;)或空行不终止并执行块。通过在新行上单独输入句点(。)来终止PL / SQL子程序。您还可以通过在新行上单独输入斜杠(/)来终止并执行PL / SQL子程序。

您将斜杠放在与end;相同的行上,这不是有效的。你需要这样做:

CREATE OR REPLACE PROCEDURE procDegrees1
AS
BEGIN
  FOR record IN (SELECT * FROM UserFriends WHERE PlayerID < FriendsWith)
  LOOP
    INSERT INTO UserFriendsCopy(PlayerID,FriendsWith)
    VALUES(record.PlayerID, record.FriendsWith);
  END LOOP;
END;
/

当你使用execute调用它时,你应该以分号结束,而不是斜杠:

EXECUTE procDegrees1;

这是一个匿名块的SQL * Plus简写,在execute成为匿名块中的单个语句之后你所拥有的,所以它被扩展用于实际执行,并且与这样做:

BEGIN
  procDegrees1;
END;
/

如果语句本身导致错误,您可以看到。但重要的是要注意execute这不是SQL语句,而是 client 命令。 SQL * Plus和SQL Developer都认可它,但其他客户可能没有。

我在评论中提到您使用Squirrel时,我开始回答这个问题。我不知道Squirrel是否允许execute,但是你得到的错误表明没有。如果它没有,那么您将需要使用扩展的匿名阻止表格,该表格可以在任何地方使用。


支持execute CALL procDegrees1 的Google suggests但您可以这样做:

{{1}}

......但我不知道这是否真的......