oracle
データベースに約20個のテーブルがあり、すべてにitemIdというインデックスフィールドがあるシナリオがあります。20 個のテーブルすべてから ID (101 と呼ばれる) を持つレコードをコピーし、それらを新しい ID (102 と呼ばれる) で挿入したいと考えています。functions/procedures
テーブルリストが将来大きくなる可能性があるため、カーソルを 20 個または 20 個にしたくありません。より良い方法でこれを達成するのを手伝ってください。
1 に答える
テーブルの数が変動する可能性があるため、目的を達成するには動的 SQL を使用する必要があります。次のようなものがうまくいけば役立つはずです。
DECLARE
l_insert_column_list VARCHAR2(4000);
l_select_column_list VARCHAR2(4000);
BEGIN
FOR table_rec IN (SELECT table_name
FROM user_tab_columns
WHERE UPPER(column_name) = 'ITEMID')
LOOP
l_insert_column_list := '';
l_select_column_list := '';
FOR col_rec IN (SELECT column_name
FROM user_tab_columns
WHERE table_name = table_rec.table_name)
LOOP
l_insert_column_list := l_insert_column_list || col_rec.column_name || ',';
IF UPPER(col_rec.column_name) = 'ITEMID' THEN
l_select_column_list := l_select_column_list || '102,';
ELSE
l_select_column_list := l_select_column_list || col_rec.column_name || ',';
END IF;
END LOOP;
l_insert_column_list := RTRIM(l_insert_column_list, ',');
l_select_column_list := RTRIM(l_select_column_list, ',');
EXECUTE IMMEDIATE 'INSERT INTO ' || table_rec.table_name || ' ('
|| l_insert_column_list || ') SELECT ' || l_select_column_list ||
' FROM ' || table_rec.table_name || ' WHERE ITEMID = 101';
END LOOP;
END;
/
ここでの考え方は、データ ディクショナリ ビューを使用して、列user_tab_columns
を持つすべてのテーブルを一覧表示することです。ITEMID
そのようなテーブルごとuser_tab_columns
に、テーブル内のすべての列をリストし、SQL 文字列を作成してデータをコピーします。
ここでいくつかの仮定を立てました。
すべてのテーブルが同じスキーマにあります。そうでない場合は、
all_tab_columns
代わりにを使用user_tab_columns
し、スキーマの所有者をtable_rec
SQL 文字列に含めて、 も使用する必要がある場合がありますtable_rec.table_name
。テーブルまたは列の名前に、二重引用符で囲む必要がある名前がありません。(その場合は、SQL 文字列を調整して二重引用符を含める必要があります。)
テーブル内のすべての列名には 4000 文字で十分です。(列名は 30 文字に制限されているため、この問題を引き起こすには 100 を超える列が必要になります。)
このスクリプトをデータベースに解放する前に、生成されている SQL 文字列を確認できるようにEXECUTE IMMEDIATE
、 への呼び出しに置き換えることを強くお勧めします。dbms_output.put_line