Oracle 错误 - ORA-00907: 缺少右括号
Posted
技术标签:
【中文标题】Oracle 错误 - ORA-00907: 缺少右括号【英文标题】:Oracle error - ORA-00907: missing right parenthesis 【发布时间】:2011-11-01 21:46:44 【问题描述】:我正在为这个 Oracle 错误而摸不着头脑。以下查询完美运行:
SELECT
V.PROJECTID,
(SELECT WM_CONCAT(DISTINCT NAME)
FROM TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE PROJECTID=V.PROJECTID
AND VERSIONID=V.VERSIONID) as Methods
FROM TPM_PROJECTVERSION V
但是,我想按字母顺序返回我的合并列表,因为我很挑剔。你会认为我会这样做:
SELECT
V.PROJECTID,
(SELECT WM_CONCAT(DISTINCT NAME)
FROM TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE PROJECTID=V.PROJECTID
AND VERSIONID=V.VERSIONID ORDER BY NAME) as Methods
FROM TPM_PROJECTVERSION V
但是,当我尝试这个时,我得到了错误:
[Error] Script lines: 15-19 ------------------------
ORA-00907: missing right parenthesis
我可以在自己的 SELECT 语句中运行查询,如下所示:
SELECT WM_CONCAT(DISTINCT NAME)
FROM TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE PROJECTID=240
AND VERSIONID=1
ORDER BY NAME
它运行良好。我的括号比太阳马戏团的队伍更平衡。为什么会出错?
【问题讨论】:
我认为这行不通。聚合不受 ORDER BY 的影响。请对其进行测试,如果需要,我将发布一个用户定义的聚合函数,它会自行排序。不幸的是,我没有支持 WM_CONCAT 的版本。 等你说对了。整点是没有意义的,如果我将独立示例更改为ORDER BY NAME DESC
,那么我会得到相同的结果。我只是假设它有效,因为这些值恰好按字母顺序排列。无论如何,我大概可以用一个简单的 LINQ 表达式对它们进行排序。
this page 上的 LISTAGG 示例似乎按字母顺序排序,但我并不十分熟悉该语法,因此不确定这是否也适用于 WM_CONCAT。如果没有,您可以随时使用 LISTAGG,如果这不起作用,我将在今天晚些时候发布解决方法。
【参考方案1】:
我认为聚合的 WM_CONCAT 函数不受 ORDER BY 的影响。
因此,正如承诺的那样,自定义聚合对结果进行排序。也可以在早期版本中使用。
-- A string table type to hold the values to concat. I limited it to 4000 because
-- of trouble with the driver I use. You should be able to change it to 32767, or
-- whatever is VARCHAR2's max size.
CREATE OR REPLACE TYPE TT_STRING as table of varchar2(4000);
-- An aggregate type for the concatenation. It uses the string table to
-- hold all values, and sorts it when you're done aggregating.
CREATE OR REPLACE TYPE AT_CONCATSORTED as object
(
V_ITEMS TT_STRING,
static function ODCIAggregateInitialize(
P_CONTEXT in out AT_CONCATSORTED)
return number,
member function ODCIAggregateIterate(
self in out AT_CONCATSORTED,
P_VALUE in varchar2)
return number,
member function ODCIAggregateTerminate(
self in AT_CONCATSORTED,
P_RESULT out varchar2,
P_FLAGS in number)
return number,
member function ODCIAggregateMerge(
self in out AT_CONCATSORTED,
P_CONTEXT in AT_CONCATSORTED)
return number
);
create or replace type body AT_CONCATSORTED is
static function ODCIAggregateInitialize(
P_CONTEXT in out AT_CONCATSORTED)
return number
is
begin
if P_CONTEXT is null then
P_CONTEXT := AT_CONCATSORTED(TT_STRING(''));
else
P_CONTEXT.V_ITEMS.delete;
end if;
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(
self in out AT_CONCATSORTED,
P_VALUE in varchar2)
return number
is
begin
self.V_ITEMS.extend;
self.V_ITEMS(self.V_ITEMS.last) := P_VALUE;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(
self in AT_CONCATSORTED,
P_RESULT out varchar2,
P_FLAGS in number)
return number
is
V_SORTEDITEMS TT_STRING;
begin
select
cast(multiset(select
*
from
table(self.V_ITEMS)
order by
1) as TT_STRING)
into
V_SORTEDITEMS
from
dual;
for i in V_SORTEDITEMS.first..V_SORTEDITEMS.last loop
P_RESULT := P_RESULT || V_SORTEDITEMS(i);
if i < V_SORTEDITEMS.last - 1 then
P_RESULT := P_RESULT || ', ';
end if;
end loop;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(
self in out AT_CONCATSORTED,
P_CONTEXT in AT_CONCATSORTED)
return number
is
begin
for i in P_CONTEXT.V_ITEMS.first..P_CONTEXT.V_ITEMS.last loop
self.V_ITEMS.extend;
self.V_ITEMS(self.V_ITEMS.last) := P_CONTEXT.V_ITEMS(i);
end loop;
return ODCIConst.Success;
end;
end;
-- The actual concat function
create or replace function CONCATSORTED (input varchar2) return varchar2
aggregate using AT_CONCATSORTED;
现在您的查询可能如下所示:
SELECT
V.PROJECTID,
CONCATSORTED(DISTINCT NAME) as NAMES
FROM
TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE
PROJECTID=V.PROJECTID
AND VERSIONID=V.VERSIONID) as Methods
FROM
TPM_PROJECTVERSION V
【讨论】:
不错的一个!可能也会使用它。【参考方案2】:试试
SELECT
V.PROJECTID,Methods.met
FROM
(SELECT WM_CONCAT(DISTINCT NAME)as met
FROM TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID)
WHERE PROJECTID=V.PROJECTID AND VERSIONID=V.VERSIONID ORDER BY NAME)
as Methods,TPM_PROJECTVERSION V
但我认为你应该添加一个 WHERE 子句来连接两个表......
【讨论】:
很奇怪,我得到ORA-00933: SQL command not properly ended
- 我还尝试更改我的嵌套查询以使用 ANSI 样式连接语法,但同样的错误。
去掉表别名前的“AS”关键字,我认为那里不允许。只说“方法”,而不是“作为方法”。
是的,我得到了PLS-306: wrong number or types of arguments in call to 'V'
- 太糟糕了,Oracle 无法生成对人类有意义的错误消息。反正没关系,反正你不能对聚合子句进行排序。以上是关于Oracle 错误 - ORA-00907: 缺少右括号的主要内容,如果未能解决你的问题,请参考以下文章
在 oracle 10g 中出现错误 .. 错误:- ORA-00907:缺少右括号
为啥 OraOLEDB.Oracle GetRecordSet() 会抛出“ORA-00907:缺少右括号”错误?
Oracle SQL - 奇怪的“ORA-00907 缺少右括号”错误