Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Kursor Oracle untuk penugasan

Siapkan tipe data dan fungsi pembantu:

CREATE TYPE string_list IS TABLE OF VARCHAR2(2);
/

CREATE TYPE int_list IS TABLE OF INT;
/

CREATE TYPE t1_data AS OBJECT(
  vk VARCHAR2(4),
  ay VARCHAR2(2),
  an VARCHAR2(14),
  r  INT,
  c  VARCHAR2(2)
);
/

CREATE TYPE t1_table IS TABLE OF t1_data;
/

CREATE OR REPLACE FUNCTION split_String(
  i_str    IN  VARCHAR2,
  i_delim  IN  VARCHAR2 DEFAULT ','
) RETURN string_list DETERMINISTIC
AS
  p_result       string_list := string_list();
  p_start        NUMBER(5) := 1;
  p_end          NUMBER(5);
  c_len CONSTANT NUMBER(5) := LENGTH( i_str );
  c_ld  CONSTANT NUMBER(5) := LENGTH( i_delim );
BEGIN
  -- https://stackoverflow.com/a/35577315/1509264
  -- License: CC BY-SA 4.0
  IF c_len > 0 THEN
    p_end := INSTR( i_str, i_delim, p_start );
    WHILE p_end > 0 LOOP
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, p_end - p_start );
      p_start := p_end + c_ld;
      p_end := INSTR( i_str, i_delim, p_start );
    END LOOP;
    IF p_start <= c_len + 1 THEN
      p_result.EXTEND;
      p_result( p_result.COUNT ) := SUBSTR( i_str, p_start, c_len - p_start + 1 );
    END IF;
  END IF;
  RETURN p_result;
END;
/

Kemudian Anda dapat menggunakan fungsi:

CREATE FUNCTION pick_values RETURN t1_table PIPELINED
IS
  TYPE t2_type IS TABLE OF t2%ROWTYPE;
  
  t2_data t2_type;
BEGIN
  -- https://stackoverflow.com/a/67398434/1509264
  -- License: CC BY-SA 4.0
  SELECT *
  BULK COLLECT INTO t2_data
  FROM  t2;
  
  FOR cur IN ( SELECT * FROM t1 ORDER BY r )
  LOOP
    DECLARE
      a_freqs  INT_LIST := INT_LIST();
      cum_freq INT := 0;
      taken    STRING_LIST := SPLIT_STRING( cur.an, ', ' );
      idx      INT;
      c        T2.A%TYPE;
    BEGIN
      a_freqs.EXTEND(t2_data.COUNT);
      FOR i IN 1 .. t2_data.COUNT LOOP
        IF ( t2_data(i).a = cur.ay AND t2_data(i).c > 0 )
           OR ( cur.ay IS NULL AND t2_data(i).a NOT MEMBER OF taken AND t2_data(i).c > 0 )
        THEN
          a_freqs(i) := cum_freq + t2_data(i).c;
          cum_freq := cum_freq + t2_data(i).c;
        ELSE
          a_freqs(i) := cum_freq;
        END IF;
      END LOOP;
      IF cum_freq > 0 THEN
        idx := FLOOR(DBMS_RANDOM.VALUE(0, cum_freq));
        FOR i IN 1 .. t2_data.COUNT LOOP
          IF idx < a_freqs(i) THEN
            c := t2_data(i).a;
            t2_data(i).c := t2_data(i).c - 1;
            EXIT;
          END IF;
        END LOOP;
      END IF;
      PIPE ROW(
        t1_data(
          cur.vk, cur.ay, cur.an, cur.r, c
        )
      );
    END;
  END LOOP;
END;
/

Yang mana, untuk data sampel Anda:

CREATE TABLE t1 (vk, ay, an, r) as
    select 'VK1', null, 'A1, A2', 1 from dual union all
    select 'VK2', null, null, 2 from dual union all
    select 'VK3', null, 'A1, A2, A3, A4', 3 from dual union all
    select 'VK4', null, 'A2', 4 from dual union all
    select 'VK5', null, null, 5 from dual union all
    select 'VK6', null, null, 6 from dual union all
    select 'VK7', 'A3', null, 7 from dual union all
    select 'VK8', null, null, 8 from dual union all
    select 'VK9', null, null, 9 from dual union all
    select 'VK10', null, null, 10 from dual union all
    select 'VK11', null, null, 11 from dual union all
    select 'VK12', null, null, 12 from dual union all
    select 'VK13', 'A3', null, 13 from dual union all
    select 'VK14', null, null, 14 from dual union all
    select 'VK15', 'A3', null, 15 from dual union all
    select 'VK16', null, null, 16 from dual union all
    select 'VK17', null, null, 17 from dual union all
    select 'VK18', null, null, 18 from dual union all
    select 'VK19', null, null, 19 from dual union all
    select 'VK20', null, null, 20 from dual;

CREATE TABLE t2 (a, c) as
    select 'A1', 4 from dual union all
    select 'A2', 10 from dual union all
    select 'A3', 2 from dual union all
    select 'A4', 10 from dual;

Kemudian:

SELECT * FROM PICK_VALUES();

Dapat menghasilkan:

VK AY AN B C VK1A1, A21A4VK22A2VK3A1, A2, A3, A43VK4A24A1VK55A2VK66A2VK7A37A3VK88A1VK99A2VK1010A4VK1111A2VK1212A1VK13A313A3VK174quotVK19A414A4VK15A4VK19

db<>main biola di sini




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mendapatkan output dari dbms_output.get_lines menggunakan JDBC

  2. Bagaimana Mendapatkan Quarter From Date di Oracle?

  3. Dapatkan PANJANG dari RAW PANJANG

  4. .patch_storage

  5. kolom tidak diizinkan di sini kesalahan dalam pernyataan INSERT