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

时间:2015-11-26 10:13:49

标签: sql oracle

我想使用Common表表达式和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命令未正确结束"   *原因:
  *操作:

2 个答案:

答案 0 :(得分:2)

等价物是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;

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

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

对于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文本。

答案 1 :(得分:0)

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
顺便说一下:你根本不需要交叉申请:

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