是否有更短的方法来更新 Oracle SQL 上的范围值列?

Posted

技术标签:

【中文标题】是否有更短的方法来更新 Oracle SQL 上的范围值列?【英文标题】:Is there a shorter way to update a column with range values on Oracle SQL? 【发布时间】:2020-01-06 07:03:30 【问题描述】:

更新脚本会是这样的

UPDATE TABLE_A
SET COLUMN_A = (range values (1,10)
WHERE  COLUMN_B = 'Descriptions'

这样当我运行下面的查询时

SELECT COLUMN_B, min(COLUMN_A ), max(COLUMN_A )
FROM TABLE_A
WHERE COLUMN_B = 'Descriptions'
group by COLUMN_B ;

COLUMN_A 的最小值为 1,最大值为 10。

【问题讨论】:

这没有意义。你想要达到什么目的?最终,您将 COLUMN_A 的值更新为 10(最后一个更新语句中的值)。此外,没有WHERE 子句。这意味着表的每条记录将更新为 10 您正在使用新值更新同一列。您是否尝试更新行号而不是使用相同的值设置整列。 抱歉,会有 WHERE 条件,例如 WHERE COLUMN_B = 'Descptions' 很难理解你想要达到什么目的。请退后一步,尽量解释清楚。如果您使用示例数据集发布创建脚本并提供预期的输出,这将有很大帮助。 好的,谢谢,我更新了问题。 【参考方案1】:
UPDATE TABLE_A 
   SET COLUMN_A = CEIL(DBMS_RANDOM.VALUE * 10) 
 WHERE COLUMN_B = 'Descriptions';

oracle 中没有“范围”函数,但您可以使用 dbms_random 来模拟它,它生成一个介于 0 和 1 之间的值。将它乘以 10,得到一个介于 0 和 10 之间的值(不包括 10)。向上取整(使用 CEIL 函数),这样您就可以得到 1 到 10 的值。 请注意,在此示例中,您将获得介于 1 和 10 之间的随机值,不能保证您包含值 1 和 10,并且可能会有重复。

【讨论】:

【参考方案2】:

假设您有一些示例数据:

CREATE TABLE table_a ( Column_A, Column_B ) AS
SELECT   0, 'Descriptions' FROM DUAL UNION ALL
SELECT 100, 'Descriptions' FROM DUAL UNION ALL
SELECT   3, 'Range1'       FROM DUAL UNION ALL
SELECT   5, 'Range2'       FROM DUAL UNION ALL
SELECT   6, 'Range2'       FROM DUAL UNION ALL
SELECT   7, 'Range2'       FROM DUAL;

您想更新Descriptions 使其范围为1-10,还想更新Range1 范围为42-50(但样本数据中只有一行)和@ 987654325@ 的范围为 0-9(但示例数据中有两行以上)。然后你可以使用MERGE 声明:

MERGE INTO table_a dst
USING (
  WITH ranges ( Column_A, Column_B, rn ) AS (
    SELECT  1, 'Descriptions', 1 FROM DUAL UNION ALL
    SELECT 10, 'Descriptions', 0 FROM DUAL UNION ALL
    SELECT 42, 'Range1',       1 FROM DUAL UNION ALL
    SELECT 50, 'Range1',       0 FROM DUAL UNION ALL
    SELECT  0, 'Range2',       1 FROM DUAL UNION ALL
    SELECT  9, 'Range2',       0 FROM DUAL
  )
  SELECT r.Column_A,
         r.Column_B,
         a.rid
  FROM   ranges r
  LEFT OUTER JOIN (
    SELECT ROWID  AS rid,
           ROW_NUMBER() OVER ( PARTITION BY Column_B ORDER BY ROWNUM ) AS rn,
           Column_B
    FROM   table_a
  ) a
  ON ( r.Column_B = a.Column_B AND MOD( a.rn, 2 ) = r.rn )
) src
ON ( src.rid = dst.ROWID )
WHEN MATCHED THEN
  UPDATE SET Column_A = src.Column_A
WHEN NOT MATCHED THEN
  INSERT ( Column_A, Column_B )
  VALUES ( src.Column_A, src.Column_B );

输出将是:

SELECT * FROM table_a;
COLUMN_A | COLUMN_B --------: | :----------- 1 |说明 10 |说明 42 |范围1 0 |范围2 9 |范围2 0 |范围2 50 |范围1

您可以看到 Range1 的额外行已创建,Range2 的所有行已更新。

db小提琴here

【讨论】:

以上是关于是否有更短的方法来更新 Oracle SQL 上的范围值列?的主要内容,如果未能解决你的问题,请参考以下文章

给定文件系统路径,是不是有更短的方法来提取没有扩展名的文件名?

Oracle SQL - 是不是有更有效的方法来组织大量案例语句

位置更新的时间间隔更短

有没有比 alloc 和 initWithFormat 更短的方法来从两种不同的数据类型创建 NSString?

Oracle UTL_HTTP 请求返回比在 Python 或 curl 中完成相同请求时更短的响应

PyQt 多个 tablewidgets 和 tabwidgets