Oracle 错误 - ORA-00907:缺少右括号

发布于 2024-12-13 02:37:28 字数 1008 浏览 3 评论 0原文

我对这个 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

并且它运行良好。我的括号比太阳马戏团更平衡。为什么会出现错误?

I'm scratching my head over this Oracle error. The following query works perfectly:

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

However, I want to return my concantonated list in alphabetical order because I'm picky like that. You'd think I would do:

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

However, when I try this I get the error:

[Error] Script lines: 15-19 ------------------------
ORA-00907: missing right parenthesis

I can run the query in its own SELECT statement, like so:

SELECT WM_CONCAT(DISTINCT NAME) 
FROM TPM_TRAININGPLAN JOIN TPM_DELIVERYMETHODS USING (METHODID) 
WHERE PROJECTID=240 
AND VERSIONID=1 
ORDER BY NAME

And it runs fine. My parenthesis are more balanced than a Cirque du Soleil troop. Why the error?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

匿名的好友 2024-12-20 02:37:28

我认为聚合的 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

I think the aggregated WM_CONCAT function isn't affected by ORDER BY.

Therefor, as promised, a custom aggregation that sorts the results. Can be used in earlier versions too.

-- 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;

Now your query could look something like this:

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
微凉 2024-12-20 02:37:28

尝试

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 子句来连接两个表......

try

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

But I think you should add a WHERE clause for joining the two tables....

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文