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

我建立了一个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

最佳答案
SQL*Plus reference says

SQL*Plus treats PL/SQL subprograms in the same manner as SQL commands, except that a semicolon (;) or a blank line does not terminate and execute a block. Terminate PL/SQL subprograms by entering a period (.) by itself on a new line. You can also terminate and execute a PL/SQL subprogram by entering a slash (/) by itself on a new line.

您将斜杠放在与结尾相同的行上;这是无效的.你需要这样做:

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简写,执行后的内容成为匿名块中的单个语句,因此它被扩展用于实际执行,与执行此操作相同:

BEGIN
  procDegrees1;
END;
/

您可以看到,如果语句本身导致错误.但重要的是要注意执行它不是SQL语句,它是一个客户端命令. SQL * Plus和SQL Developer认可它,但其他客户可能不会.

在您评论中提到您使用Squirrel之前,我开始回答这个问题.我不知道Squirrel是否允许执行,但是你得到的错误表明没有.如果没有,那么您将需要使用扩展的匿名块表单,该表单应该可以在任何地方使用.

不支持执行的Google suggests,但您可以执行此操作:

CALL procDegrees1

……但我不知道这是不是真的……

点赞