【问题标题】:ORA-01735: Invalid ALTER TABLE option when deallocated unused space on a segment with dynamic SQLORA-01735: 使用动态 SQL 释放段上的未使用空间时,ALTER TABLE 选项无效
【发布时间】:2018-01-28 06:25:12
【问题描述】:

我开发了一个简单的打包程序,允许段(在 HWM 之上)未使用的空闲空间。它接收模式名称、表名称和 KEEP clause 的值作为参数。

当我使用 EXECUTE IMMEDIATE 语句运行 DDL 语句时,它告诉我 ALTER 选项无效。如果我从普通终端运行相同的语句,则可以正常工作。

BLOQUES ASIGNADOS -> 8
BLOQUES OCUPADOS -> 5
TAMAÑO INICIAL -> 9
LIBERANDO ESPACIO ALTER TABLE SERGIO11.EMPLOYEES DEALLOCATE UNUSED;
ERROR : -1735MENSAJE: ORA-01735: opción ALTER TABLE no válida

这里是过程的定义:

PROCEDURE RELEASE_UNUSED_SPACE(
            p_owner IN DBA_TABLES.OWNER%TYPE,
            p_table IN DBA_TABLES.TABLE_NAME%TYPE,
            p_keep IN NUMBER DEFAULT NULL,
            p_unit IN VARCHAR2 DEFAULT 'M'
        ) AS
            UNAVAILABLE_UNIT EXCEPTION;
            TYPE R_SEGMENT_BLOCKS_INFO IS RECORD (
                occupied_blocks   DBA_SEGMENTS.BLOCKS%TYPE,
                assigned_blocks   DBA_SEGMENTS.BLOCKS%TYPE,
                initial_extent    DBA_SEGMENTS.INITIAL_EXTENT%TYPE
            );

            v_segmentBlocksInfo R_SEGMENT_BLOCKS_INFO;
            v_deallocate_sql VARCHAR2(100);

        BEGIN

            IF(p_owner IS NULL OR p_table IS NULL) THEN
                RAISE INVALID_ARGUMENTS;
            END IF;

            IF (p_keep IS NOT NULL AND UPPER(p_unit) NOT IN ('M', 'K')) THEN
                RAISE UNAVAILABLE_UNIT;
            END IF;

            SELECT T.BLOCKS, S.BLOCKS, CEIL(S.INITIAL_EXTENT / 8000)
            INTO v_segmentBlocksInfo
            FROM DBA_TABLES T, DBA_SEGMENTS S
            WHERE S.SEGMENT_NAME = T.TABLE_NAME AND S.OWNER = T.OWNER
                AND S.OWNER = T.OWNER
                AND T.TABLE_NAME = UPPER(p_table) AND T.OWNER = UPPER(p_owner);

            PRINT_LINE('BLOQUES ASIGNADOS -> ' || v_segmentBlocksInfo.assigned_blocks);
            PRINT_LINE('BLOQUES OCUPADOS -> ' || v_segmentBlocksInfo.occupied_blocks);
            PRINT_LINE('TAMAÑO INICIAL -> ' || v_segmentBlocksInfo.initial_extent);

            IF v_segmentBlocksInfo.occupied_blocks < v_segmentBlocksInfo.assigned_blocks THEN
                v_deallocate_sql := 'ALTER TABLE ' || p_owner || '.' || p_table || ' DEALLOCATE UNUSED';
                IF p_keep IS NOT NULL THEN
                    v_deallocate_sql := v_deallocate_sql || ' KEEP ' || p_keep || 'M'; 
                END IF;
                v_deallocate_sql := v_deallocate_sql || ';';
                PRINT_LINE('LIBERANDO ESPACIO ' || v_deallocate_sql);
                EXECUTE IMMEDIATE v_deallocate_sql;
            END IF;

        EXCEPTION
            WHEN NO_DATA_FOUND THEN
                PRINT_LINE('TABLE ' || p_table || ' ON SCHEMA ' || p_owner || ' NOT EXISTS');
            WHEN UNAVAILABLE_UNIT THEN
                PRINT_LINE('UNIT OF MEASURE NOT VALID. Only M or K is allowed');
            WHEN OTHERS THEN
                PRINT_LINE('ERROR : ' || SQLCODE || 'MENSAJE: ' || SQLERRM);
        END RELEASE_UNUSED_SPACE;

例如,当使用此参数执行过程时,结果语句将是:

EXEC MANAGEMENT_OF_TABLES_AND_INDEX.RELEASE_UNUSED_SPACE('SERGIO11', 'EMPLOYEES');

ALTER TABLE SERGIO11.EMPLOYEES DEALLOCATE UNUSED;

我已将 ALTER ANY TABLE 权限明确授予所有者用户,该用户也是执行该权限的同一用户。

有谁知道问题出在哪里。提前谢谢!!!。

【问题讨论】:

    标签: oracle stored-procedures plsql dynamic-sql plsqldeveloper


    【解决方案1】:

    尝试删除此语句

    v_deallocate_sql := v_deallocate_sql || ';';
    

    所以你的句子应该是:

    ALTER TABLE SERGIO11.EMPLOYEES DEALLOCATE UNUSED
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-23
      • 2021-11-26
      相关资源
      最近更新 更多