【问题标题】:Insert statement inserts wrong random numbers into table OracleInsert 语句将错误的随机数插入到 Oracle 表中
【发布时间】:2021-09-19 09:23:59
【问题描述】:

我尝试生成示例数据,因此我想在我的 Oracle 表中插入多行。列值应该在 1-5 之间,并且应该是完全随机的。我需要 20 个随机整数。

我的插入语句:

BEGIN
FOR i IN 163 .. 400 LOOP
INSERT ALL INTO results
  (student_id,OPN1,OPN2,OPN3,OPN4,AGG1,AGG2,AGG3,AGG4,NEU1,NEU2,NEU3,NEU4,EXT1,EXT2,EXT3,EXT4,CSN1,CSN2,CSN3,CSN4)
  VALUES
  (i,
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)))
  SELECT * FROM DUAL;
END LOOP;
COMMIT;
END;

它有效,但在一行中的数字都是一样的。它不会为每一列生成一个新的随机数,只是一个并将其插入到我表的所有字段中。为什么会这样?您可以在 102 id 行之后看到它。第一个插入的行(163 id)已经错了。

【问题讨论】:

  • 好吧,如果数字生成是真正随机的,那么获得具有相同数字的所有列的实例是完全有可能的。掷硬币五次。每次翻转都会产生一个随机结果。并且很有可能连续获得五个“正面”。

标签: sql oracle for-loop random sql-insert


【解决方案1】:

INSERT ALL 有一些怪癖,但你在这里不需要它,你可以删除 ALL 和虚拟 select 使其成为一个简单的插入值语句:

BEGIN
FOR i IN 163 .. 400 LOOP
INSERT INTO results
  (student_id,OPN1,OPN2,OPN3,OPN4,AGG1,AGG2,AGG3,AGG4,NEU1,NEU2,NEU3,NEU4,EXT1,EXT2,EXT3,EXT4,CSN1,CSN2,CSN3,CSN4)
  VALUES
  (i,
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)));
END LOOP;
COMMIT;
END;
/

您也不需要 PL/SQL,您可以使用分层查询(或递归 CTE)而不是循环:

INSERT INTO results
  (student_id,OPN1,OPN2,OPN3,OPN4,AGG1,AGG2,AGG3,AGG4,NEU1,NEU2,NEU3,NEU4,EXT1,EXT2,EXT3,EXT4,CSN1,CSN2,CSN3,CSN4)
SELECT
  level + 162,
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5)),
  round(dbms_random.value(1,5))
FROM dual
CONNECT BY level <= 1 + 400 - 163;

或如@MTO 建议的那样,使用地板而不是圆形:

INSERT INTO results
  (student_id,OPN1,OPN2,OPN3,OPN4,AGG1,AGG2,AGG3,AGG4,NEU1,NEU2,NEU3,NEU4,EXT1,EXT2,EXT3,EXT4,CSN1,CSN2,CSN3,CSN4)
SELECT
  level + 162,
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6)),
  floor(dbms_random.value(1,6))
FROM dual
CONNECT BY level <= 1 + 400 - 163;

db<>fiddle(为简单起见,列较少)。

【讨论】:

  • @Phaki 不要使用round(dbms_random.value(1,5)),因为你会得到 1 和 5 的频率是其他数字的一半。使用FLOOR(DBMS_RANDOM.VALUE(1,6)),您将获得频率相等的值。
  • 哦,不知道!将更新我的行,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多