簡體   English   中英

PL/SQL 將數據插入一列,其值對應於另一列的值

[英]PL/SQL insert data into a column with values corresponding to values of another column

有一個表結構類似於 customer_id number(10), listing_id number(12)。

現在這個表中的數據有點超過1000萬,所以我被賦予了在表中添加process_id的任務,以便在以后的操作中可以批量處理數據。

所以我在表中添加了一列 process_id
alter table temp_lid_cid add process_id number(1);

現在我必須將進程ID隨機添加到customer_ids 1 2 3 4 5 6 7,以便where process_id = $1的條件下根據他們的process_ids進行處理

有數百萬的數據,所以我寫了一個簡單的 PL

declare 
i temp_lid_cid.customer_id%type; 
c temp_lid_cid.process_id%type;
begin
c:=0;
for i in (select customer_id from temp_lid_cid)
loop
    if (c = 7) then
        c := 0;
    end if;
    c := c+1;
        execute immediate q'[insert into temp_lid_cid(process_id) select :var1 as process_id from temp_lid_cid where customer_id = :var2]'using i,c;
  end loop;
end;

它拋出這個錯誤

Error report -
ORA-06550: line 12, column 145:
PLS-00457: expressions have to be of SQL types
ORA-06550: line 12, column 9:
PL/SQL: Statement ignored
06550. 00000 -  "line %s, column %s:\n%s"
*Cause:    Usually a PL/SQL compilation error.
*Action:

我也嘗試在不立即執行的情況下運行插入語句,但它仍然拋出錯誤。我還嘗試為 PL 之外的單個客戶運行插入語句,它工作正常。

如果您可以建議任何其他方式來做我想做的事情,而無需 PL,那也很棒。

現在這個表中的數據略高於1000萬,所以我被賦予了在表中添加process_id的任務,以便可以批量處理數據

Insert將向您的表中插入一個新行。 您需要一個Update語句來滿足您的要求。 見下文:

DECLARE
    i   temp_lid_cid.customer_id%TYPE;
    c   temp_lid_cid.process_id%TYPE;

BEGIN
    c   := 0;
    FOR i IN (SELECT customer_id FROM temp_lid_cid ) 
LOOP
        IF ( c = 7 )
        THEN
            c   := 0;
        END IF;
        c   := c + 1;

        UPDATE temp_lid_cid
            SET
                process_id = c
        WHERE customer_id = i.customer_id;

    END LOOP;

    COMMIT;
END;

您的代碼中的錯誤:

在您的Loop中,customer_id 是使用i.customer_id獲取的。 因此,在您的插入語句中替換如下:

using c,i.customer_id;

建議:

由於行數為10 Million ,所以我建議使用BULK Operation 來執行Update

DECLARE   
    c   temp_lid_cid.process_id%TYPE;    
    type v_cust_id is table of temp_lid_cid.customer_id%TYPE index by pls_integer;    
    i v_cust_id;

BEGIN
    c   := 0;

    SELECT customer_id 
    BULK COLLECT INTO i
    FROM temp_lid_cid;

    FORALL rec IN 1..i.count
        UPDATE temp_lid_cid
            SET
                process_id = c + i(rec) -- Updating Process_Id with Customer_id
        WHERE customer_id = i(rec);

    COMMIT;
END;

您交換了sql類型。

declare 
i temp_lid_cid.process_id%type; 
c temp_lid_cid.customer_id%type;

為什么要使用PL/SQL塊和loop 可以使用單個merge語句完成,如下所示:(我使用的范圍是 1-4 個數字,您可以通過在合並語句中將 4 替換為 7 來使用 1-7 個數字)

Oracle 表創建:

SQL> CREATE TABLE TEMP_LID_CID (
  2      CUSTOMER_ID   NUMBER(10),
  3      LISTING_ID    NUMBER(12),
  4      PROCESS_ID    NUMBER(1)
  5  );

Table created.

向表中插入數據:

SQL> insert into temp_lid_cid values (1,10,null);

1 row created.

SQL> insert into temp_lid_cid values (1,20,null);

1 row created.

SQL> insert into temp_lid_cid values (1,30,null);

1 row created.

SQL> insert into temp_lid_cid values (1,40,null);

1 row created.

SQL> insert into temp_lid_cid values (1,50,null);

1 row created.

SQL> insert into temp_lid_cid values (2,10,null);

1 row created.

SQL> insert into temp_lid_cid values (2,20,null);

1 row created.

SQL> insert into temp_lid_cid values (2,30,null);

1 row created.

數據的當前視圖

SQL> select * from TEMP_LID_CID;

CUSTOMER_ID LISTING_ID PROCESS_ID
----------- ---------- ----------
          1         10
          1         20
          1         30
          1         40
          1         50
          2         10
          2         20
          2         30

8 rows selected.

SQL>

查詢以達到預期的結果:

SQL> MERGE INTO TEMP_LID_CID T USING (
  2                                      SELECT
  3                                          T1.*,
  4                                          T1.ROWID   AS RID,
  5                                          MOD(ROW_NUMBER() OVER(
  6                                              ORDER BY
  7                                                  T1.CUSTOMER_ID
  8                                          ), 4) AS RANDOM_PROCESS_ID -- replace 4 with 7
  9                                      FROM
 10                                          TEMP_LID_CID T1
 11                                  )
 12  T1 ON ( T.ROWID = T1.RID )
 13  WHEN MATCHED THEN UPDATE SET T.PROCESS_ID = DECODE(T1.RANDOM_PROCESS_ID, 0, 4, T1.RANDOM_PROCESS_ID); -- replace 4 with 7

更新后數據:

SQL> select * from TEMP_LID_CID;

CUSTOMER_ID LISTING_ID PROCESS_ID
----------- ---------- ----------
          1         10          1
          1         20          2
          1         30          3
          1         40          4
          1         50          1
          2         10          2
          2         20          3
          2         30          4

8 rows selected.

SQL>

由於 process_id 可以是隨機的,您也可以使用這樣的簡單查詢:

update temp_lid_cid set process_id = mod(rownum,7)+1;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM