如何向带引用的类型表中插入值?已尝试多种方法仍未解决
搞定带REF属性的
LINE类型表插入问题 嘿,我看你在折腾Oracle自定义对象类型的插入操作,尤其是带REF Point属性的LINE类型,这玩意儿确实容易踩坑,我来给你捋捋怎么搞定它!
先把你的代码补全梳理下
你给出的LINE类型定义还没写完,我先把它补全成可编译的完整版本(毕竟要插入数据,得先确保类型本身没问题):
-- 先定义依赖的Point类型 CREATE OR REPLACE TYPE Point AS OBJECT ( X NUMBER, Y NUMBER ); / -- 你的LINE类型定义 CREATE OR REPLACE TYPE LINE AS OBJECT ( EP1 REF Point, EP2 REF Point, MEMBER FUNCTION getOrientation RETURN Char, MEMBER FUNCTION getLen Return Number, CONSTRUCTOR FUNCTION Line (EP1 REF Point, EP2 REF Point) RETURN SELF as RESULT ); / -- LINE类型的体实现(补全你没写完的部分,还修正了成员方法调用的小问题) create or replace type body line as member function getLen return number is v_length NUMBER; begin -- 调用成员方法要加SELF.,不然编译会报错 if SELF.getOrientation = 'V' then v_length := ABS(EP2.Y - EP1.Y); else v_length := ABS(EP2.X - EP1.X); end if; return v_length; end; member function getOrientation return Char is begin if EP1.X = EP2.X then return 'V'; -- 垂直线 elsif EP1.Y = EP2.Y then return 'H'; -- 水平线 else return 'O'; -- 斜线 end if; end; constructor function Line(EP1 REF Point, EP2 REF Point) return SELF as RESULT is begin SELF.EP1 := EP1; SELF.EP2 := EP2; return; end; end; / -- 假设你需要的是LINE类型的表(不管是对象表还是集合表) CREATE OR REPLACE TYPE Line_Table AS TABLE OF Line; /
插入数据的核心逻辑:先有Point的REF,才能创建Line
因为LINE的两个属性都是REF Point,这意味着你必须先把Point对象存在对象表里,才能拿到它们的引用,进而创建Line实例。
步骤1:创建Point对象表并插入基础数据
-- 创建存储Point对象的表 CREATE TABLE Point_Table OF Point; / -- 插入几个测试用的Point INSERT INTO Point_Table VALUES (Point(1, 2)); INSERT INTO Point_Table VALUES (Point(3, 2)); INSERT INTO Point_Table VALUES (Point(1, 5)); COMMIT;
步骤2:两种插入Line的方式
方式1:直接插入到持久化的Line对象表
如果你要把Line存在数据库里,先建Line的对象表,再用REF()函数获取Point的引用插入:
-- 创建Line的对象表 CREATE TABLE Line_Persist_Table OF Line; / -- 插入一条水平线((1,2)到(3,2)) INSERT INTO Line_Persist_Table SELECT Line(REF(p1), REF(p2)) FROM Point_Table p1, Point_Table p2 WHERE p1.X=1 AND p1.Y=2 AND p2.X=3 AND p2.Y=2; COMMIT;
方式2:先在内存中构建Line集合,再插入(适合批量操作)
如果要批量创建Line,用PL/SQL块先构建集合再插入更方便:
DECLARE v_line_collection Line_Table; v_p1_ref REF Point; v_p2_ref REF Point; BEGIN -- 先拿到两个Point的引用 SELECT REF(p) INTO v_p1_ref FROM Point_Table p WHERE p.X=1 AND p.Y=2; SELECT REF(p) INTO v_p2_ref FROM Point_Table p WHERE p.X=1 AND p.Y=5; -- 初始化集合,添加Line实例 v_line_collection := Line_Table(); v_line_collection.EXTEND; v_line_collection(v_line_collection.LAST) := Line(v_p1_ref, v_p2_ref); -- 把集合里的Line插入到持久化表 INSERT INTO Line_Persist_Table SELECT * FROM TABLE(v_line_collection); COMMIT; END; /
踩坑提醒
- 成员方法调用要加
SELF.:你原来的getLen方法里直接写getOrientation,Oracle会找不到这个方法,必须改成SELF.getOrientation。 - REF不能是NULL:确保你用来创建Line的Point确实存在于
Point_Table里,查询条件别写错,不然REF会是空的,插入会报错。 - 自定义构造函数不是必须的:如果你的构造函数只是简单给属性赋值,Oracle会自动生成默认构造函数,完全可以不用显式定义,除非你有额外的初始化逻辑。
内容的提问来源于stack exchange,提问作者NickM
相关产品推荐
相关产品推荐

