2011-09-21 48 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

相關問題