对象类型中%ROWTYPE的解决方法

时间:2017-02-20 11:00:29

标签: oracle plsql oracle11g

我是PL / SQL的新手并试图创建一个引用表行的对象:

CREATE OR REPLACE TYPE my_object AS OBJECT(
  table_row my_table%ROWTYPE
);

编译器给出错误消息PLS-00329。 好的,现在我知道我不能引用像这样的表格。但是有解决方法吗?

2 个答案:

答案 0 :(得分:5)

您必须列出对象类型声明中的所有字段。你提到你担心容易出错。您可以通过PL / SQL块(或将表和对象名称传递到的过程)半自动化对象创建。

假设您将表定义为;

CREATE TABLE my_table (
  ID NUMBER(38),
  col_1 DATE,
  col_2 NUMBER(3, 2),
  col_3 VARCHAR2(10),
  col_4 CLOB
);

您可以从数据字典中提取列名和数据类型,并构建对象创建语句:

DECLARE
  v_stmt VARCHAR2(4000);
BEGIN
  v_stmt := 'CREATE OR REPLACE TYPE my_object AS OBJECT(';

  FOR r IN (
    SELECT column_name,
    CAST (data_type || CASE 
      WHEN data_type IN ('VARCHAR', 'VARCHAR2', 'NVARCHAR2', 'RAW', 'CHAR')
        THEN '(' || data_length || ')'
      WHEN data_type IN ('NUMBER')
          AND (data_precision IS NOT NULL OR data_scale IS NOT NULL)
        THEN '(' || data_precision || CASE
          WHEN data_scale > 0 THEN ',' || data_scale
        END || ')'
      END AS VARCHAR2(30)) AS data_type,
      CASE WHEN column_id < MAX(column_id) OVER () THEN ',' END AS comma
    FROM user_tab_columns
    WHERE table_name = 'MY_TABLE'
    ORDER BY column_id
  )
  LOOP
    v_stmt := v_stmt || r.column_name || ' ' || r.data_type || r.comma;
  END LOOP;

  v_stmt := v_stmt || ')';

  dbms_output.put_line(v_stmt); -- just for debugging
  EXECUTE IMMEDIATE v_stmt;
END;
/

如果需要,您也可以提取和使用可空标志,但这里可能没用。 (这可以从a describe replacement改编。可能有一些数据类型处理不当但它涵盖了常见的数据类型;如果你有UDT列或其他奇怪的列,则需要扩展以适当地包含这些。 )

dbms_output只显示生成的语句,以便于调试:

CREATE OR REPLACE TYPE my_object AS OBJECT(ID NUMBER(38),COL_1 DATE,COL_2 NUMBER(3,2),COL_3 VARCHAR2(10),COL_4 CLOB)

PL/SQL procedure successfully completed.

当该语句也被执行时,对象被创建:

desc my_object;

Name  Null? Type         
----- ----- ------------ 
ID          NUMBER(38)   
COL_1       DATE         
COL_2       NUMBER(3,2)  
COL_3       VARCHAR2(10) 
COL_4       CLOB         

如果要添加功能,可以使用生成的create语句作为起点,并编辑它以在手动运行之前添加所需内容,而不是使用execute immediate

答案 1 :(得分:0)

听起来很方便,我认为类型的语法不可能有任何类型,因为类型必须提供SQL接口 - 你必须能够描述类型并查看其属性列表,属性需要是发布在user_type_attrs中,您必须能够从中创建子类型和对象关系表和列,在查询中使用它并查看列投影等。

使用select *创建视图时,列列表会在创建时展开,但如果稍后更改表格则不会重建。因此,即使Oracle确实提供了一种类似于类型的方法,我怀疑它们必须遵循相同的模式,即在创建时简单地生成列表,然后将其保留给您进行维护,以避免管理依赖项的复杂性和级联失效,特别是当类型本身具有复杂的依赖关系时,type evolution周围的限制。