我建立了一个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
答案 0 :(得分:2)
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}}
......但我不知道这是否真的......