[英]SQL subquery to return MIN of a column and corresponding values from another column
[英]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.