ORA-00933: 使用 CROSS APPLY 时 SQL 命令未正确结束

Posted

技术标签:

【中文标题】ORA-00933: 使用 CROSS APPLY 时 SQL 命令未正确结束【英文标题】:ORA-00933: SQL command not properly ended while using CROSS APPLY 【发布时间】:2015-11-26 10:13:48 【问题描述】:

我想使用公用表表达式和 CROSS APPLY 对 v$sql 运行查询。

这是我的 SQL:

WITH CTE AS
  (SELECT
    SUM(ELAPSED_TIME/1000/1000)/SUM(EXECUTIONS) AS Avg_Elapsed_Time_sec,
    SUM(ELAPSED_TIME/1000/1000) AS Sum_Elapsed_Time_sec,
    SUM(ELAPSED_TIME/1000/1000/(executions))    AS Sum_Avg_Elapsed_Time_sec,
    SUM(EXECUTIONS)                       AS Sum_Executions,
    SUM(ROWS_PROCESSED)                   AS Sum_Row_Processed,
    SUM(ROWS_PROCESSED) / SUM(executions) AS Avg_Row_Processed,
    SUM(FETCHES)                          AS Sum_Fetches,
    SUM(FETCHES) / SUM(EXECUTIONS)        AS Avg_Fetch,
    SUM(DISK_READS)                       AS Sum_DiskRead,
    SUM(DISK_READS) / SUM(EXECUTIONS)     AS Avg_DiskRead,
    SUM(APPLICATION_WAIT_TIME)            AS Sum_Application_Wait_Time,
    SUM(CONCURRENCY_WAIT_TIME)            AS Sum_Concurrency_Wait_Time,
    SUM(USER_IO_WAIT_TIME)                AS Sum_User_IO_Wait_Time,
    SUM(PLSQL_EXEC_TIME)                  AS Sum_PlSql_Exec_Time,
    SUM(OPTIMIZER_COST)                   AS Sum_Optimizer_Cost,
    SQL_ID,
    HASH_VALUE,
    COUNT(*)                              AS Entries
  FROM
    v$sql
  WHERE
    executions > 1
  GROUP BY
    SQL_ID,
    HASH_VALUE
  ORDER BY
    Avg_Elapsed_Time_sec DESC
  )
SELECT  D.SQL_FULLTEXT,CTE.* FROM v$sql 
CROSS APPLY //Error in this line
(
   select SQL_FULLTEXT from v$sql where v$sql.SQL_ID=CTE.SQL_ID and rownum=1
) D

如何解决此错误? 但我收到此错误:

ORA-00933: SQL 命令未正确结束 00933. 00000 - “SQL 命令未正确结束” *原因: *行动:

【问题讨论】:

应该使用横向连接。 From hereCROSS APPLY 有 JOIN 没有的功能 Instesd of CROSS APPLY 我使用横向连接,但我得到另一个错误_缺少关键字_ 【参考方案1】:

等价的将是cross join lateral。您还有从 CTE 错误中选择的 select 语句。您需要从 CTE 中选择,而不是从 v$sql

WITH cte AS
(
  SELECT .... 
)
SELECT cte.*, d.sql_fulltext
FROM cte --<< select from the CTE, not from V$SQL here!
  CROSS JOIN LATERAL (
      SELECT sql_fulltext
      FROM v$sql 
      WHERE cte.sql_id = v$sql.sql_id
        AND rownum = 1
) d
ORDER BY Avg_Elapsed_Time_sec DESC;

order byinside CTE 没有意义,如果您将 CTE 加入其他内容,它将不会被保留。您需要将其移到从 CTE 中选择的语句中。

您可以将CROSS JOIN LATERAL 替换为CROSS APPLY,但CROSS JOIN LATERAL 是标准SQL 而APPLY 不是


Edit 对于 Oracle 11,您需要使用如下内容:

WITH cte AS (
   SELECT ...
)
SELECT cte.*, 
       d.sql_fulltext
FROM cte --<< select from the CTE, not from V$SQL here!
  JOIN (
      SELECT sql_id, 
             sql_fulltext, 
             row_number() over (partition by sql_id order by child_number) as rn
      FROM v$sql 
) d ON d.sql_id = cte.sql_id and d.rn = 1
ORDER BY Avg_Elapsed_Time_sec DESC;

V$SQL 可以包含同一个 SQL_ID 的多行(对于不同的子游标)。上面的语句显示了第一个子游标的 SQL 文本。

【讨论】:

感谢您的回答,但我在 CROSS JOIN LATERAL 行中遇到了同样的错误 @kaja 那你没有使用 Oracle 12 哦,你是对的,我使用的是这个版本:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production。这个版本有解决方案吗?【参考方案2】:

SELECT  D.SQL_FULLTEXT,CTE.* FROM v$sql 
CROSS APPLY //Error in this line
(
   select SQL_FULLTEXT from v$sql where v$sql.SQL_ID=CTE.SQL_ID and rownum=1
) D

您不是从 CTE 中选择(而是两次都直接从 v$sql 中选择)。但在交叉应用中,您引用 CTE.SQL_ID。

你可能想选择 FROM CTE,所以交叉应用会知道你在说什么 :-)

SELECT  D.SQL_FULLTEXT,CTE.* FROM CTE
CROSS APPLY
(
   select SQL_FULLTEXT from v$sql where v$sql.SQL_ID=CTE.SQL_ID and rownum=1
) D

顺便说一句:您根本不需要 CROSS APPLY:

SELECT 
  (select SQL_FULLTEXT from v$sql where v$sql.SQL_ID = CTE.SQL_ID and rownum = 1),
  CTE.* 
FROM CTE;

【讨论】:

以上是关于ORA-00933: 使用 CROSS APPLY 时 SQL 命令未正确结束的主要内容,如果未能解决你的问题,请参考以下文章

ORA-00933: SQL 命令未正确结束

ORA-00933: SQL 命令未正确结束 00933. 00000 - “SQL 命令未正确结束

为啥会出现“ORA-00933:SQL 命令未正确结束”错误(立即执行)?

ORA-00933: 运行创建序列命令时 SQL 命令未正确结束

SQL 错误:ORA-00933:SQL 命令未正确结束 00933。00000 -“SQL 命令未正确结束”

“ORA-00933: SQL 命令未正确结束”