2011-09-21 42 views
0

给定一个表T(x, y, z, t, u, v, ...)是否有可能在Oracle中编写该查询而不列出所有列(在SELECT中还是在INSERT部分中)?如何复制只更改一列的值而不列出其他列的一组行?

INSERT INTO T (x, y, z, t, u, v, ...) 
SELECT 'new', y, z, t, u, v, ... 
    FROM T 
WHERE x = 'old' 

的影响是,它x值的所有行都是相同的,只是现在x值。

+0

你试过了吗? –

+0

@Hugh Jones:当然,INSERTING没有列出列将插入默认值。我想复制现有的行。 – Benoit

+0

您在上面显示的查询将具有您正在寻找的效果。 –

回答

2

“是否有可能在甲骨文写这个查询没有列出所有 列(不管是在SELECT还是在INSERT部分)“

否。避免输入显式投影的唯一方法是使用所有表格的列。你不这样做,因为你想使用文字而不是列X。这意味着您必须在SELECT投影中列出所有其他列。

当然,您不必在INSERT子句中指定列。

在开发人员偶尔希望对年“除了”语法,是这样的:

select * except X from t 

,但它从未进入ANSI标准。事实上,我怀疑它是否被讨论过。


“PLSQL答案,欢迎呢!”

好的,这里是使用数据字典生成动态插入语句的概念证明。

它作以下假设:

  1. 你只是想替换一个列的值。
  2. 您要替换的列是一个字符串数据类型。
  3. 您想克隆源表中的所有记录。

如果这些假设中的任何一个错误,您将需要调整代码。

该过程围绕USER_TAB_COLUMNS表循环,将列排序为表的投影顺序。它将列名连接到INSERT语句的SELECT子句中,除非名称是连接所提供的文字时替换列的名称。最后它使用本地动态SQL来运行组装的INSERT语句。

create or replace procedure clone_minus_one 
    (p_sub_col in user_tab_columns.column_name%type 
     , p_sub_val in varchar2) 
is 
    stmt varchar2(32767) := 'insert into source_table select '; 
begin 
    for lrec in (select column_name 
         , column_position 
        from user_tab_columns. 
        where table_name = 'SOURCE_TABLE' 
        order by column_position) 
    loop 
     if lrec.column_position != 1 
     then 
      stmt := stmt ||','; 
     end if; 
     if lrec.column_name != p_sub_col 
     then 
      stmt := stmt ||lrec.column_name; 
     else 
      stmt := stmt ||''''||p_sub_val||''''; 
     end if; 
    end loop; 
    stmt := stmt || ' from source_table'; 
    execute immediate stmt; 
end; 
/
+0

谢谢!会尝试。如果我改进它,我可以编辑该答案吗? – Benoit

+0

@Benoit - 敲你自己。 – APC

1

您可以按照您的描述完成,只要您选择的列正确排列。

以下是有效的

INSERT INTO T 
SELECT 'new', y, z, t, u, v, ... 
    FROM T 
WHERE x = 'old' 

,或者你可以试试这个(粗糙的脚本未测试)

CREATE TABLE TEMPTABLE AS SELECT * FROM T WHERE X = 'Old'; 

UPDATE TEMPTABLE SET X='New'; 

INSERT INTO T (SELECT * FROM TEMPTABLE); 

DROP TABLE TEMPTABLE; 
+0

您必须在选择中列出所需的所有列,但只要它们按正确的顺序映射到列,则查询将起作用。 –

+0

@Hugh Jones:好的,重新提出的问题:我想避免列出INSERT部分中的所有列,并在SELECT部分​​列出除x以外的所有列。这不够清楚吗? – Benoit

+0

我迂腐了吗?抱歉。 –

0

以下是走得太远,以免一些打字海事组织,但我喜欢挑战,所以这里去...

insert into T 
select * from T 
where x='old'; 
commit; 

-- update every other row to 'new' 
update T 
set x='new' 
where rowid in 
(
select rowid from 
    (select rownum rnum, rowid row_id 
    from T 
    where x='old' 
) 
where mod(rnum,2)=0 
); 
commit; 

在2个步骤,而我个人倒在只查询表格的all_tab_columns(按column_id排序)并复制/粘贴到我的脚本/过程中。但可能是一些其他的原因,以避免这一点,不知道。

+0

谢谢,这似乎很聪明,但1.可能有独特的约束(唉),2.顺序的rownum分配永远不能保证,所以你不能可靠地认为每第二行是一个新插入的行,除非你ORDER BY *(哈哈,需要在这里列出所有的列!) – Benoit

+0

是的,对不起benoit,这是正确的,这个答案将无法可靠的工作...顺序。试图让我觉得太聪明;) – tbone

+0

虽然这是一个不错的尝试! – Benoit

相关问题