繁体   English   中英

插入…选择…有子查询或无列顺序

[英]insert into… select … with subquery or without column order

我正在使用Oracle数据库,不知道是否可以编写类似以下内容的代码:

INSERT INTO CL (select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME='CL')
SELECT * FROM CLT;

要么:

INSERT INTO CL (select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME='CL')
SELECT (select COLUMN_NAME from USER_TAB_COLUMNS where TABLE_NAME='CL') FROM CLT;

因此,想法是两个表都具有相同的列,但列顺序不匹配,所以当我尝试做简单时

INSERT INTO CL 
SELECT * FROM CLT;

我不断收到ORA-00932:数据类型不一致,如果我一一指定所有列,则不会发生。 但是我不想这样做,因为我的表有约50列,并且我想要一个健壮的解决方案,以后也可以将其应用于其他表。

这就是为什么我在考虑使用子查询在INSERT INTO查询中获取列名的原因,但是这在sql中是不可能的,或者我做错了什么。

是否有任何方法可以跳过其中的列顺序(并强制sql使用名称?)或在该查询中使用子查询以相同顺序获得两倍的所有列名称?

PS。 我当时正在考虑重新排序,以将它们引导至“不可见”并返回“可见”,但我的版本不支持此功能。 而且它不会像我需要的那样可重用。

不,您不能使用子查询来生成列列表作为SQL语句的一部分。

您可以从数据字典生成完整的语句:

select 'insert into cl ("'
  || listagg(column_name, '","') within group (order by column_id)
  || '") select "'
  || listagg(column_name, '","') within group (order by column_id)
  || '" from clt'
from user_tab_columns where table_name = 'CLT';

然后复制并粘贴,或使用匿名块中的动态SQL:

declare
  stmt varchar2(4000);
begin
  select 'insert into cl ("'
    || listagg(column_name, '","') within group (order by column_id)
    || '") select "'
    || listagg(column_name, '","') within group (order by column_id)
    || '" from clt'
  into stmt
  from user_tab_columns where table_name = 'CLT';

  dbms_output.put_line(stmt); -- to check and debug
  execute immediate stmt;
end;
/

有几个虚拟表:

create table clt (col1 number, col2 date, col3 varchar2(10));
create table cl (col3 varchar2(10), col1 number, col2 date);

insert into clt (col1, col2, col3) values (42, date '2018-07-12', 'Test');

insert into cl
select * from clt;

SQL Error: ORA-00932: inconsistent datatypes: expected NUMBER got DATE

运行该块可以得到:

insert into cl ("COL1","COL2","COL3") select "COL1","COL2","COL3" from clt

PL/SQL procedure successfully completed.

select * from cl;

COL3             COL1 COL2      
---------- ---------- ----------
Test               42 2018-07-12

如果您可能经常想这样做,您也可以将该匿名块转换为采用两个表名的过程(您说它需要可重用,但这可能意味着相同的表,并且可能只是脚本中的一个块)。

您还可以走得更远,只包括出现在两个表中的列,或者验证数据类型是否完全匹配; 尽管还有更多工作,可能完全没有必要。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM