如何使用列中的值作为重复次数

huangapple go评论70阅读模式
英文:

How to use a value in a column as repetition count

问题

我有一个需要根据另一个表中的值运行多次的更新语句。以下是这些表的样子:

表1

ROW_ID CLOB_TEXT
1 文本
2 文本

表2

HOW_MANY_TIMES ROW_ID
1 1
4 2

基本上,更新语句应该在第一行上运行,但它将运行多少次取决于第二个表的第一列。我在两个表上都有ROW_ID列来将它们关联起来,以防止重复。

我应该将我的第二个表转换为下面的格式并为每一行运行更新吗?或者可能还有其他方法吗?

COL1 ROW_ID
1 1
1 2
2 2
3 2
4 2

我可以为每一行执行单个更新,但似乎无法根据另一个表中的计数器在循环中执行更新。

英文:

I have an update statement that needs to be run as many times as a value in another table. Here are what the tables look like

TABLE 1

ROW_ID CLOB_TEXT
1 text
2 text

TABLE 2

HOW_MANY_TIMES ROW_ID
1 1
4 2

Basically update statement should run on the first row, but how many times that it will runn will be dependent based on the first col from the second table. And i have ROW_ID col on the both tables to link them to prevent repetitions.

Should i convert my second table to the format below and run updates for each row? Or is there another way to do it maybe?

COL1 ROW_ID
1 1
1 2
2 2
3 2
4 2

I can do single updates for each row but i can't seem to do it in a loop(?) based on a counter from another table it seems.

答案1

得分: 1

你可以在单个MERGE语句中完成它(对于大型数据集,这比在PL/SQL中使用循环要高效得多):

MERGE INTO table_1 dst
USING (
  SELECT t1.ROWID AS rid,
         t2.ROW_ID,
         l.idx
  FROM   table_1 t1
         INNER JOIN table_2 t2
         ON (t1.ROW_ID = t2.ROW_ID)
         CROSS APPLY(
           SELECT LEVEL AS idx
           FROM   DUAL
           WHERE  LEVEL <= t2.how_many_times
           CONNECT BY LEVEL <= t2.how_many_times
         ) l
) src
ON (dst.ROWID = src.rid AND src.idx = 1)
WHEN MATCHED THEN
  UPDATE
  SET clob_text = src.idx
WHEN NOT MATCHED THEN
  INSERT (row_id, clob_text) VALUES (src.row_id, src.idx);

对于示例数据:

CREATE TABLE TABLE_1 (ROW_ID, CLOB_TEXT) AS
SELECT 1, EMPTY_CLOB() || 'text' FROM DUAL UNION ALL
SELECT 2, EMPTY_CLOB() || 'text' FROM DUAL;

CREATE TABLE TABLE_2 (HOW_MANY_TIMES, ROW_ID) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 4, 2 FROM DUAL;

然后,在MERGE之后,table_1 包含以下内容:

ROW_ID CLOB_TEXT
1 1
2 1
2 2
2 3
2 4

fiddle

英文:

You can do it in a single MERGE statement (which for large data sets is going to be much more efficient than loops in PL/SQL):

MERGE INTO table_1 dst
USING (
  SELECT t1.ROWID AS rid,
         t2.ROW_ID,
         l.idx
  FROM   table_1 t1
         INNER JOIN table_2 t2
         ON (t1.ROW_ID = t2.ROW_ID)
         CROSS APPLY(
           SELECT LEVEL AS idx
           FROM   DUAL
           WHERE  LEVEL <= t2.how_many_times
           CONNECT BY LEVEL <= t2.how_many_times
         ) l
) src
ON (dst.ROWID = src.rid AND src.idx = 1)
WHEN MATCHED THEN
  UPDATE
  SET clob_text = src.idx
WHEN NOT MATCHED THEN
  INSERT (row_id, clob_text) VALUES (src.row_id, src.idx);

Which, for the sample data:

CREATE TABLE TABLE_1 (ROW_ID, CLOB_TEXT) AS
SELECT 1, EMPTY_CLOB() || 'text' FROM DUAL UNION ALL
SELECT 2, EMPTY_CLOB() || 'text' FROM DUAL;

CREATE TABLE TABLE_2 (HOW_MANY_TIMES, ROW_ID) AS
SELECT 1, 1 FROM DUAL UNION ALL
SELECT 4, 2 FROM DUAL;

Then, after the MERGE, table_1 contains:

ROW_ID CLOB_TEXT
1 1
2 1
2 2
2 3
2 4

fiddle

答案2

得分: 0

这是你所讨论的内容吗?

开始
  对于 cur_2  (选择 row_id, how_many_times  table2) 循环
    对于 i  1  cur_2.how_many_times 循环
      更新 table1 设置
        clob_text = 替换(clob_text, 'A', 'B')
        其中 row_id = cur_2.row_id;
    结束循环;
  结束循环;
结束;
/
英文:

Is this what you're talking about?

begin
  for cur_2 in (select row_id, how_many_times from table2) loop
    for i in 1 ..cur_2.how_many_times loop
      update table1 set
        clob_text = replace(clob_text, 'A', 'B')
        where row_id = cur_2.row_id;
    end loop;
  end loop;
end;
/ 

huangapple
  • 本文由 发表于 2023年7月17日 20:26:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704449.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定