我的 Oracle 语法有什么问题?

What is wrong with my Oracle syntax?

我有一个 SQL 存储过程需要转换为 Oracle。我在语法上遇到了一些麻烦。

我得到的当前错误是:

Error(75,1): PLS-00103: 遇到符号 "DROP" 期望以下之一: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge

我想我还有很多。谁能帮我弄清楚我做错了什么?

这是我的资料:

create or replace PROCEDURE "PROCEDURE1" 
(
  IN_FEATURENAME IN NVARCHAR2 
, OUT_O_RC OUT SYS_REFCURSOR 
) AS


BEGIN
execute immediate 'CREATE TABLE t_name_match( ' || 
'KBID       int     NOT NULL, ' || 
'SYMBOLID   int     NOT NULL,' || 
'FEATURE_NAME   varchar(30) NULL';

execute immediate 'CREATE TABLE t_compat_match( ' || 
'KBID       int     NOT NULL, ' || 
'SYMBOLID   int     NOT NULL,' || 
'FEATURE_NAME   varchar(30) NULL';
/*******************************************************************************    ***
** Name matches
    ********************************************************************************    ***/
/*
** Load matches to Name Table
*/
INSERT INTO t_name_match (KBID, SYMBOLID, FEATURE_NAME)
SELECT  KBID, SYMBOLID, FEATURENAME
  from  FEATURE_MASTER
 where  FEATURENAME like IN_FEATURENAME;

/*******************************************************************************    ***
** Compatibility Statement matches
********************************************************************************    ***/
/*
** Load matches to Compatibility table
*/
 INSERT INTO t_compat_match (KBID, CHARID, SYMBOLID)
SELECT  KBID, CHARID, SYMBOLID
  from  FEATURE_COMPAT
 where  INSTR(IN_FEATURENAME, LINE) > 0;

INSERT INTO t_name_match (KBID, SYMBOLID, FEATURE_NAME)
 SELECT cm.KBID, cm.SYMBOLID, NULL
   from (SELECT DISTINCT KBID, SYMBOLID
        from t_compat_match)    cm
  where NOT EXISTS  (SELECT 'X'
               from t_name_match nm
              where nm.KBID     = cm.KBID
                and nm.SYMBOLID = cm.SYMBOLID);


UPDATE  t_name_match

  SET FEATURE_NAME = (SELECT FEATURENAME
  from  FEATURE_MASTER

  where nm.FEATURE_NAME IS NULL
   and  fm.KBID     = nm.KBID
    and fm.SYMBOLID = nm.SYMBOLID);

 OPEN OUT_O_RC FOR
/*******************************************************************************    ***
** Return result set
********************************************************************************     ***/
SELECT  DISTINCT m.MODELNAME, m.VERSION, m.PLANTID, m.FROMDATE, m.TODATE,
     m.BUILD, m.KBID, nm.SYMBOLID, nm.FEATURE_NAME as FEATURENAME
  FROM  t_name_match        nm,
     KB_MASTER      m
  WHERE     m.KBID = nm.KBID 
    AND     m.MODELGROUP    = 'F'
 ORDER BY m.MODELNAME, m.VERSION;

/*
** Clean up
*/

DROP TABLE #t_name_match
DROP TABLE #t_compat_match

RETURN 0;
END PROCEDURE1;

这里是原SQL代码:

**  Create the stored procedure
*/
ALTER PROCEDURE [dbo].[fcs_feature_usage]
(   @search_string      varchar(50),
    @debug_flag     char(1)     = 'N'
)
as

DECLARE @error          int,
    @search_string_like varchar(51)

SELECT  @search_string_like     = Upper(@search_string) + '%'

IF (@debug_flag = 'Y') OR (@debug_flag = 'X')
    SELECT  GetDate() as "fcs_feature_usage Started"

/*
** Store matching results in intermediate tables (required to avoid 
** JOIN, DISTINCT, and SORT between two, 2 million row tables).
*/
CREATE TABLE #t_name_match
(   KBID        int     NOT NULL,
    SYMBOLID    int     NOT NULL,
    FEATURE_NAME    varchar(30) NULL
)

CREATE TABLE #t_compat_match
(   KBID        int     NOT NULL,
    CHARID      int     NOT NULL,
    SYMBOLID    int     NOT NULL
)
/*******************************************************************************    ***
** Name matches
********************************************************************************    ***/
/*
** Load matches to Name Table
*/
INSERT INTO #t_name_match (KBID, SYMBOLID, FEATURE_NAME)
SELECT  KBID, SYMBOLID, FEATURE_NAME
  from  FCS..T_FEATURE_MASTER
 where  feature_name like @search_string_like

select  @error = @@error
IF (@error <> 0)
   BEGIN
    GOTO error_routine
   END

IF (@debug_flag = 'Y')
    SELECT  GetDate() as "#t_name_match Loaded"

/*******************************************************************************    ***
** Compatibility Statement matches
********************************************************************************    ***/
/*
** Load matches to Compatibility table
*/
INSERT INTO #t_compat_match (KBID, CHARID, SYMBOLID)
SELECT  KBID, CHARID, SYMBOLID
  from  FCS..T_FEATURE_COMPAT
 where  charindex(@search_string, LINE) > 0

select  @error = @@error
IF (@error <> 0)
   BEGIN
    GOTO error_routine
   END

IF (@debug_flag = 'Y')
    SELECT  GetDate() as "#t_compat_match Loaded"

/*
** Add to the name matches table a list of features which had 
** the given string in one of their compatibility statements.
**
** The below join, results in a complete index scan, so broke into
** two statements (INSERT & UPDATE):
**
INSERT INTO #t_name_match (KBID, SYMBOLID, FEATURE_NAME)
SELECT  cm.KBID, cm.SYMBOLID, fm.FEATURE_NAME
  from  FCDB..T_FEATURE_MASTER      fm,
    (SELECT DISTINCT KBID, SYMBOLID
       from #t_compat_match)    cm
 where  fm.KBID     = cm.KBID
   and  fm.SYMBOLID = cm.SYMBOLID
   and  NOT EXISTS  (SELECT 'X'
               from #t_name_match nm
              where nm.KBID     = cm.KBID
                and nm.SYMBOLID = cm.SYMBOLID)
*/
INSERT INTO #t_name_match (KBID, SYMBOLID, FEATURE_NAME)
SELECT  cm.KBID, cm.SYMBOLID, NULL
  from  (SELECT DISTINCT KBID, SYMBOLID
       from #t_compat_match)    cm
 where  NOT EXISTS  (SELECT 'X'
               from #t_name_match nm
              where nm.KBID     = cm.KBID
                and nm.SYMBOLID = cm.SYMBOLID)

select  @error = @@error
IF (@error <> 0)
   BEGIN
    GOTO error_routine
   END

UPDATE  #t_name_match
   set  FEATURE_NAME = fm.FEATURE_NAME
  from  #t_name_match       nm,
    FCS..T_FEATURE_MASTER   fm
 where  nm.FEATURE_NAME IS NULL
   and  fm.KBID     = nm.KBID
   and  fm.SYMBOLID = nm.SYMBOLID

select  @error = @@error
IF (@error <> 0)
   BEGIN
    GOTO error_routine
   END

IF (@debug_flag = 'Y')
    SELECT  GetDate() as "Added #t_compat_match to #t_name_match"

/*******************************************************************************    ***
** Return result set
    ********************************************************************************        ***/
SELECT  DISTINCT m.Model_Name, m.Version, m.plant_id fac_cd,     m.FROM_DATE,           m.TO_DATE,
        m.build, m.KBID, nm.SYMBOLID, left(nm.FEATURE_NAME,12) featureName
      FROM  #t_name_match       nm,
       T_MODEL_MASTER       m
         WHERE  m.KBID      = nm.KBID 
       AND  m.Model_Group   = 'F'
    ORDER BY m.Model_Name, m.version

    /*
    ** Clean up
    */
DROP TABLE #t_name_match
DROP TABLE #t_compat_match

IF (@debug_flag = 'Y') OR (@debug_flag = 'X')
    SELECT  GetDate() as "fcs_feature_usage Completed"

RETURN 0

/*********************************************************************
** Error Processing Routine. 
**********************************************************************/
error_routine:

DROP TABLE #t_name_match
 DROP TABLE #t_compat_match

RETURN  @error

DROP 是一个 DDL 语句,在 PL/SQL 代码中无效。

用"execute immediate"替换

execute immediate "DROP TABLE t_name_match"

您几乎肯定不想在 Oracle 过程中创建和删除 table。 Oracle 临时 table 与 SQL 服务器临时 table 非常不同。在 SQL 服务器中,临时 table 的定义在会话本地(假设 table 名称以 # 为前缀)。 Oracle 没有这种本地临时文件的概念 table。 Oracle 中的临时 table 是全局的——定义对所有会话可见,数据仅对本地会话可见。这意味着您将在定义永久 tables 的同时在您的过程之外创建一次临时 tables-- 并且您不会将它们丢弃在过程中.

类似

CREATE GLOBAL TEMPORARY TABLE t_name_match
(   KBID        int     NOT NULL,
    SYMBOLID    int     NOT NULL,
    FEATURE_NAME    varchar2(30) NULL
)
ON COMMIT DELETE ROWS;

CREATE GLOBAL TEMPORARY TABLE t_compat_match
(   KBID        int     NOT NULL,
    CHARID      int     NOT NULL,
    SYMBOLID    int     NOT NULL
)
ON COMMIT DELETE ROWS;


create or replace PROCEDURE "PROCEDURE1" 
(
  IN_FEATURENAME IN NVARCHAR2 
, OUT_O_RC OUT SYS_REFCURSOR 
) AS


BEGIN
/*******************************************************************************    ***
** Name matches
    ********************************************************************************    ***/
/*
** Load matches to Name Table
*/
INSERT INTO t_name_match (KBID, SYMBOLID, FEATURE_NAME)
SELECT  KBID, SYMBOLID, FEATURENAME
  from  FEATURE_MASTER
 where  FEATURENAME like IN_FEATURENAME;

/*******************************************************************************    ***
** Compatibility Statement matches
********************************************************************************    ***/
/*
** Load matches to Compatibility table
*/
 INSERT INTO t_compat_match (KBID, CHARID, SYMBOLID)
SELECT  KBID, CHARID, SYMBOLID
  from  FEATURE_COMPAT
 where  INSTR(IN_FEATURENAME, LINE) > 0;

INSERT INTO t_name_match (KBID, SYMBOLID, FEATURE_NAME)
 SELECT cm.KBID, cm.SYMBOLID, NULL
   from (SELECT DISTINCT KBID, SYMBOLID
        from t_compat_match)    cm
  where NOT EXISTS  (SELECT 'X'
               from t_name_match nm
              where nm.KBID     = cm.KBID
                and nm.SYMBOLID = cm.SYMBOLID);


UPDATE  t_name_match

  SET FEATURE_NAME = (SELECT FEATURENAME
  from  FEATURE_MASTER

  where nm.FEATURE_NAME IS NULL
   and  fm.KBID     = nm.KBID
    and fm.SYMBOLID = nm.SYMBOLID);

 OPEN OUT_O_RC FOR
/*******************************************************************************    ***
** Return result set
********************************************************************************     ***/
SELECT  DISTINCT m.MODELNAME, m.VERSION, m.PLANTID, m.FROMDATE, m.TODATE,
     m.BUILD, m.KBID, nm.SYMBOLID, nm.FEATURE_NAME as FEATURENAME
  FROM  t_name_match        nm,
     KB_MASTER      m
  WHERE     m.KBID = nm.KBID 
    AND     m.MODELGROUP    = 'F'
 ORDER BY m.MODELNAME, m.VERSION;

END PROCEDURE1;

可能有用。事实上,您在注释块之前有 OPEN OUT_O_RC FOR 并且在注释块之后有 SELECT 使得该段代码有点难以理解。我也没有寻找其他语法错误。

当然,在 Oracle 中,首先使用临时 tables 是非常不常见的——做一个直接的端口并在 Oracle 中为每个使用它们的过程使用临时 tables在 SQL 服务器中将创建一些非常非惯用的 Oracle 代码,这些代码的效率可能会低于预期。在您的系统中最终出现成百上千个临时 table 也可能很烦人,尤其是当不同的 SQL 服务器程序创建具有相同名称和不同列集的临时 table 时。使用本地集合或简单地不首先具体化数据并直接查询底层永久性 table 可能会更好地为您服务。这取决于您为什么首先在 SQL 服务器中使用临时 tables。例如,请参阅 alternatives to temporary tables.

上的此线程