如何循环遍历模式中的所有表并使用相同的值更新所有表的 MIN(主键列)值

问题描述 投票:0回答:1

寻找一种方法来更新模式中所有表的主键列的最小值,我能够从所需的模式中获取主键列名称和表名称的值,但不确定如何使用该选择使用 PLSQL 查询输出来更新值

无法找到解决问题的正确方法

oracle plsql oracle11g
1个回答
0
投票

为什么要更新主键列值?您确定这是个好主意吗?因为,

  • 您打算如何处理外键约束?您无法更新从其他表引用的主键
  • 复合主键(由两列或更多列组成的主键)怎么样?
  • 不同的数据类型怎么样?主键可以是数字,但也可以是例如VARCHAR2 或 DATE。

无论如何:这里的示例展示了如何做到这一点 - 动态 SQL。阅读代码中的注释。

在我的示例架构中,有几个带有主键的表:

SQL> select c.table_name, c.column_name, p.data_type
  2  from user_cons_columns c join
  3       user_constraints t on t.constraint_name = c.constraint_name join
  4       user_tab_columns p on p.table_name = c.table_name
  5                         and p.column_name = c.column_name
  6  where t.constraint_type = 'P';

TABLE_NAME      COLUMN_NAME     DATA_TYPE
--------------- --------------- ---------------
DEPT            DEPTNO          NUMBER   --> foreign key from EMP won't allow update
EMP             EMPNO           NUMBER
COUNTRIES       CODE            VARCHAR2 --> datatype will rule out this PK
TEST            ID              NUMBER

好的,我们走吧:

SQL> set serveroutput on
SQL> declare
  2    l_str varchar2(200);
  3    l_old_pk_value number;
  4    l_new_pk_value number := -1;
  5  begin
  6    -- find primary keys whose datatype is NUMBER on position 1
  7    for cur_r in (select c.table_name, c.column_name
  8                  from user_cons_columns c join
  9                       user_constraints t on t.constraint_name = c.constraint_name join
 10                       user_tab_columns p on p.table_name = c.table_name
 11                                         and p.column_name = c.column_name
 12                  where t.constraint_type = 'P'
 13                    and p.data_type = 'NUMBER'
 14                    and c.position = 1)
 15    loop
 16      dbms_output.put_line('Working on ' || cur_r.table_name ||'.'|| cur_r.column_name);
 17      -- find minimum value of primary key column
 18      l_str := 'select min(' || cur_r.column_name ||')' ||
 19               ' from ' ||cur_r.table_name;
 20      execute immediate l_str into l_old_pk_value;
 21
 22      -- update minimum value of the primary key column to L_NEW_PK_VALUE
 23      l_str := 'update ' || cur_r.table_name || ' set ' ||
 24               cur_r.column_name || ' = ' || l_new_pk_value ||
 25               ' where ' ||cur_r.column_name || ' = ' || l_old_pk_value;
 26      -- report if something goes wrong
 27      begin
 28        execute immediate l_str;
 29      exception
 30        when others then
 31          dbms_output.put_line(cur_r.table_name ||'.'|| cur_r.column_name ||': '|| sqlerrm);
 32      end;
 33    end loop;
 34  end;
 35  /

结果:

Working on DEPT.DEPTNO
DEPT.DEPTNO: ORA-02292: integrity constraint (SCOTT.FK_EMP_DEPT) violated - child record found
Working on EMP.EMPNO
Working on TEST.ID

PL/SQL procedure successfully completed.

正如我所说,

DEPT
在外键约束上失败了。
EMP
TEST
已更新。

SQL> select * from emp where empno = -1;

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
        -1 SMITH      CLERK           7902 17-DEC-80        800                    20

SQL> select * From test;

        ID NAME
---------- --------------------
        -1 Littlefoot
         2 Bigfoot

SQL>
© www.soinside.com 2019 - 2024. All rights reserved.