在Oracle 10g上,我们需要将视图中的记录插入到表中,以支持本身没有sort或ORDER选项的哑客户端应用程序。有没有办法控制INSERT语句将记录添加到目标表的顺序?
答案 0 :(得分:11)
您可以不可靠地控制Oracle在没有ORDER BY
的情况下检索表行的顺序。
此外,如果没有/*+APPEND*/
提示,Oracle会将行物理存储在有空间的堆表中,这可能不在表的末尾!您可能认为Oracle会按顺序插入它们,但任何DML或并发活动(2个以上的会话插入)都可能会产生不同的物理组织。
您可以使用INDEX ORGANIZED table按PK的顺序存储行。此后,该表上的大多数简单查询将生成一组已排序的行。 但是,如果您没有指定ORDER BY ,则不能保证oracle将按该顺序选择行(取决于查询和访问路径,行可以按任何顺序排列)。< / p>
您也可以使用带有订单的视图,如果您无法触摸应用程序,这可能是您最好的选择(重命名表,使用表的名称创建视图,让应用程序认为它查询表)。我不知道你的情况是否可行。
答案 1 :(得分:5)
除非您指定ORDER BY,否则您永远无法保证Oracle将从SELECT返回行的顺序
答案 2 :(得分:0)
只需使用ORDER BY。像
这样的东西INSERT INTO table
(
SELECT
column1, column2
FROM
view
ORDER BY
column2
)
编辑,这实际上不起作用。您可以按适当的顺序创建包含行的临时视图,然后执行插入。
答案 3 :(得分:0)
您的主要问题,即您的应用程序未向其查询添加ORDER BY的问题,可能可以通过在您要订购的列上使用索引来解决,然后使用存储的大纲来导致查询使用索引访问表。
您必须进行测试以确定这是否有效 - 请注意,仅添加INDEX()提示可能还不够,因为优化器可能会找到一种方法来在不访问索引时遵循提示按正确的顺序;如果查询加入其他表,那么排序可能会丢失。
答案 4 :(得分:0)
是, IS 是一种控制订单的方法。我通过经验找到了一张国家表,我们称之为OLD_COUNTRIES
,看起来像这样:
-----------------------------------
| ID | CODE | NAME |
-----------------------------------
|112099 | AF | Afghanistan |
|112100 | AA | Albania |
|... | .. | ... |
|112358 | ZB | Zimbabwe |
|112359 | AZ | Azores Islands |
|... | .. | ... |
-----------------------------------
我希望在主要国家/地区列表(例如亚速尔群岛和其他稍后添加的岛屿)之后添加的项目在我将其插入新表格时按字母顺序与其他国家/地区按字母顺序显示:
CREATE TABLE MYAPP.COUNTRIES
(
ID NUMBER(*, 0)
, CODE NVARCHAR2(20)
, NAME NVARCHAR2(250)
);
然后我运行它以使其工作:
INSERT /*+ append */ INTO MYAPP.COUNTRIES (ID, CODE, NAME)
SELECT ID, CODE, NAME FROM MYAPP.OLD_COUNTRIES_TABLE ORDER BY NAME ASC;
COMMIT;
我的新COUNTRIES
表通过字母按字母顺序排列就好了。
注意:COMMIT
是必需的,或者当您尝试打开表以在Oracle SQL Developer中查看它时,您将收到错误:ORA-12838: cannot read/modify an object after modifying it in parallel
。
注意:如果您不使用/*+ append */
,则不会按照您指定的顺序插入 - 它会忽略ORDER BY
。我知道当我使用ORDER BY
时它使用了/*+ append */
而不是默认为旧表或新表上的主键,因为它们都没有主键。
CAVEAT :根据接受的答案的作者,附加提示,与“任何DML或并发活动......可能产生不同的物理组织”一样。虽然可能是真的,但是在此期间不要进行任何并发操作,并且在我的代码中有COMMIT
语句,这样就不会发生!