You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PL/SQL存储过程创建表时触发PLS-00103编译错误排查求助

解决PLS-00103错误:你的PL/SQL存储过程问题分析与修复

嘿,我来帮你搞定这个困扰你的PLS-00103错误!咱们一步步拆解问题,然后给出修复后的代码:

核心错误原因

你遇到的PLS-00103错误,主要是因为几个PL/SQL语法和执行规则的问题:

1. PL/SQL块中不能直接执行DDL语句

PL/SQL的普通执行块(BEGIN...END)里不允许直接写CREATE TABLE这类DDL语句,必须通过动态SQL(EXECUTE IMMEDIATE)来执行,因为DDL属于SQL引擎直接处理的语句,不能直接嵌入PL/SQL的流程控制中。

2. DECLARE块的位置错误

你在存储过程的BEGIN之后又写了DECLARE,这不符合PL/SQL的结构规范:存储过程的声明部分(变量、常量等)必须放在AS/IS和BEGIN之间,不能在执行块中间插入DECLARE。

3. FOR循环的变量引用错误

你的循环变量PARTKEY和SUPPKEY是从单列查询中获取的标量值,不是记录类型,所以不能用PARTKEY.PS_PARTKEY这种方式引用,直接用变量名对应的列字段即可。

4. 不必要的循环内COMMIT

循环里每次INSERT就COMMIT会增加事务开销,还可能导致数据不一致,建议把COMMIT放在所有数据插入操作完成之后。

修复后的完整代码

SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE THELLO AS
    -- 这里可以放存储过程需要的变量声明(如果有的话)
BEGIN
    -- 用动态SQL执行CREATE TABLE语句
    EXECUTE IMMEDIATE 'CREATE TABLE NEW_PART(
        P_PARTKEY NUMBER(12) NOT NULL,
        P_NAME VARCHAR(55) NOT NULL,
        P_MFGR VARCHAR(25) NOT NULL,
        P_BRAND CHAR(10) NOT NULL,
        P_TYPE VARCHAR(25) NOT NULL,
        P_SIZE NUMBER(12) NOT NULL,
        P_CONTAINER CHAR(10) NOT NULL,
        P_RETAILPRICE NUMBER(12,2) NOT NULL,
        P_COMMENT VARCHAR(23) NOT NULL,
        CONSTRAINT NEW_PART_PKEY PRIMARY KEY (P_PARTKEY),
        CONSTRAINT NEW_PART_CHECK1 CHECK(P_PARTKEY >= 0),
        CONSTRAINT NEW_PART_CHECK2 CHECK(P_SIZE >= 0),
        CONSTRAINT NEW_PART_CHECK3 CHECK(P_RETAILPRICE >= 0)
    )';

    EXECUTE IMMEDIATE 'CREATE TABLE NEW_SUPPLIER(
        S_SUPPKEY NUMBER(12) NOT NULL,
        S_NAME CHAR(25) NOT NULL,
        S_ADDRESS VARCHAR(40) NOT NULL,
        S_NATIONKEY NUMBER(12) NOT NULL,
        S_PHONE CHAR(15) NOT NULL,
        S_ACCTBAL NUMBER(12,2) NOT NULL,
        S_COMMENT VARCHAR(101) NOT NULL,
        CONSTRAINT NEW_SUPPLIER_PKEY PRIMARY KEY (S_SUPPKEY),
        CONSTRAINT NEW_SUPPLIER_FKEY1 FOREIGN KEY (S_NATIONKEY) REFERENCES NATION(N_NATIONKEY),
        CONSTRAINT NEW_SUPPLIER_CHECK1 CHECK(S_SUPPKEY >= 0)
    )';

    EXECUTE IMMEDIATE 'CREATE TABLE NEW_PARTSUPP(
        PS_PARTKEY NUMBER(12) NOT NULL,
        PS_SUPPKEY NUMBER(12) NOT NULL,
        PS_AVAILQTY NUMBER(12) NOT NULL,
        PS_SUPPLYCOST NUMBER(12,2) NOT NULL,
        PS_COMMENT VARCHAR(199) NOT NULL,
        CONSTRAINT NEW_PARTSUPP_PKEY PRIMARY KEY (PS_PARTKEY, PS_SUPPKEY),
        CONSTRAINT NEW_PARTSUPP_FKEY1 FOREIGN KEY (PS_PARTKEY) REFERENCES NEW_PART(P_PARTKEY),
        CONSTRAINT NEW_PARTSUPP_FKEY2 FOREIGN KEY (PS_SUPPKEY) REFERENCES NEW_SUPPLIER(S_SUPPKEY),
        CONSTRAINT NEW_PARTSUPP_CHECK1 CHECK(PS_PARTKEY >= 0),
        CONSTRAINT NEW_PARTSUPP_CHECK2 CHECK(PS_AVAILQTY >= 0),
        CONSTRAINT NEW_PARTSUPP_CHECK3 CHECK(PS_SUPPLYCOST >= 0)
    )';

    -- 插入NEW_PART数据:修正循环变量引用
    FOR PARTKEY IN (SELECT DISTINCT PS_PARTKEY FROM PARTSUPP) LOOP
        INSERT INTO NEW_PART
        SELECT * FROM PART WHERE P_PARTKEY = PARTKEY.PS_PARTKEY;
    END LOOP;

    -- 插入NEW_SUPPLIER数据:修正循环变量引用
    FOR SUPPKEY IN (SELECT DISTINCT PS_SUPPKEY FROM PARTSUPP) LOOP
        INSERT INTO NEW_SUPPLIER
        SELECT * FROM SUPPLIER WHERE S_SUPPKEY = SUPPKEY.PS_SUPPKEY;
    END LOOP;

    -- 插入NEW_PARTSUPP数据
    INSERT INTO NEW_PARTSUPP
    SELECT * FROM PARTSUPP 
    WHERE PS_PARTKEY IN (SELECT P_PARTKEY FROM NEW_PART)
      AND PS_SUPPKEY IN (SELECT S_SUPPKEY FROM NEW_SUPPLIER);

    -- 统一提交所有操作
    COMMIT;
END THELLO;
/
show errors
prompt Done.

额外提示

  • 如果这些表可能已经存在,建议在CREATE TABLE前加上DROP TABLE ... CASCADE CONSTRAINTS;的动态SQL,或者用CREATE TABLE ... IF NOT EXISTS(Oracle 12c及以上支持)。
  • 尽量避免用SELECT *插入数据,显式指定列名会让代码更健壮,避免原表结构变化导致的错误。

内容的提问来源于stack exchange,提问作者Jonas Chen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:32