Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Cursor für dynamischen Tabellennamen in PL/SQL-Prozedur öffnen

Ich würde dies als eine einzelne Insert-as-Select-Anweisung tun, die nur durch die Tatsache kompliziert wird, dass Sie den Tabellennamen übergeben, also müssen wir dynamisches SQL verwenden.

Ich würde es so machen:

CREATE OR REPLACE PROCEDURE some_name(p_table_name IN VARCHAR2,
                                      p_chunk_size IN NUMBER,
                                      p_row_limit  IN NUMBER) AS

  v_table_name VARCHAR2(32); -- 30 characters for the tablename, 2 for doublequotes in case of case sensitive names, e.g. "table_name"

  v_insert_sql CLOB;
BEGIN
  -- Sanitise the passed in table_name, to ensure it meets the rules for being an identifier name. This is to avoid SQL injection in the dynamic SQL
  -- statement we'll be using later.
  v_table_name := DBMS_ASSERT.ENQUOTE_LITERAL(p_table_name);

  v_insert_sql := 'insert into chunks (common_column_name, chunk_number)'||CHR(10)|| -- replace the column names with the actual names of your chunks table columns.
                  'select common_column,'||CHR(10)||
                  '       ora_hash(substr(common_column, 1, 15), :p_chunk_size) AS chunk_number'||CHR(10)||
                  'from   '||v_table_name||CHR(10)||
                  'where  rownum <= :p_row_limit';

  -- Used for debug purposes, so you can see the definition of the statement that's going to be run.
  -- Remove before putting the code in production / convert to proper logging code:
  dbms_output.put_line(v_insert_sql);

  -- Now run the statement:
  EXECUTE IMMEDIATE v_insert_sql USING p_chunk_size, p_row_limit;

  -- I've included the p_row_limit in the above statement, since I'm not sure if your original code loops through all the rows once it processes the
  -- first p_row_limit rows. If you need to insert all rows from the p_table_name into the chunks table, remove the predicate from the insert sql and the extra bind variable passed into the execute immediate.
END some_name;
/

Indem Sie eine einzelne Insert-as-Select-Anweisung verwenden, verwenden Sie die effizienteste Art, die Arbeit zu erledigen. Die Massenerfassung (die Sie verwendet haben) würde Speicher verbrauchen (Speichern der Daten im Array) und zusätzliche Kontextwechsel zwischen den PL/SQL- und SQL-Engines verursachen, die die Insert-as-Select-Anweisung vermeidet.