Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何在Oracle中使用select更新列_Sql_Oracle_Sql Update - Fatal编程技术网

Sql 如何在Oracle中使用select更新列

Sql 如何在Oracle中使用select更新列,sql,oracle,sql-update,Sql,Oracle,Sql Update,我需要根据Name&DOB更新表中的列ID2值。我已经创建了一个oracle序列,并决定将该值填充到ID2列中,但我无法将该逻辑组合到更新查询中。请看我下面的代码,我想通过名字、DOB和更新ID2来做一组,但是我被困在逻辑的中间。如果您有sql或plsql中的任何解决方案,那么它可以工作!谢谢 CREATE SEQUENCE seq MINVALUE 1 START WITH 100 INCREMENT BY 1; UPDATE table1 SET ID2 = seq.next

我需要根据Name&DOB更新表中的列ID2值。我已经创建了一个oracle序列,并决定将该值填充到ID2列中,但我无法将该逻辑组合到更新查询中。请看我下面的代码,我想通过名字、DOB和更新ID2来做一组,但是我被困在逻辑的中间。如果您有sql或plsql中的任何解决方案,那么它可以工作!谢谢

CREATE SEQUENCE seq
  MINVALUE 1
  START WITH 100
  INCREMENT BY 1;


UPDATE table1 SET ID2 = seq.nextval
where Name= ---NOT SURE WHAT TO DO ?
select count(*) from table1
group by NAME,DOB;

假设您希望ID2值与ID1值的顺序相同,并且没有重复的ID1值,则可以通过使用具有适当窗口子句的分析函数,无顺序地执行此操作:

select name, dob, id1,
  100 + dense_rank() over (order by trunc(id1))
      + dense_rank() over (partition by trunc(id1) order by id1)/10
      as id2
from table1;

NAME  DOB               ID1        ID2
----- ---------- ---------- ----------
JIM   1991-11-30       23.1      101.1
JIM   1991-11-30       23.2      101.2
JIM   1991-11-30       23.3      101.3
TOM   1993-12-30       30.1      102.1
TOM   1993-12-30       30.2      102.2
HENRY 1994-12-03       34.1      103.1
HENRY 1994-12-03       34.2      103.2

7 rows selected. 
然后,可以将生成的表用作合并语句的一部分:

merge into table1
using (
  select name, dob, id1,
    100 + dense_rank() over (order by trunc(id1))
        + dense_rank() over (partition by trunc(id1) order by id1)/10
        as id2
  from table1
) tmp on (tmp.id1 = table1.id1)
when matched then
update set table1.id2 = tmp.id2;

7 rows merged.

select * from table1;

NAME  DOB               ID1        ID2
----- ---------- ---------- ----------
JIM   1991-11-30       23.1      101.1
JIM   1991-11-30       23.2      101.2
JIM   1991-11-30       23.3      101.3
TOM   1993-12-30       30.1      102.1
TOM   1993-12-30       30.2      102.2
HENRY 1994-12-03       34.1      103.1
HENRY 1994-12-03       34.2      103.2

7 rows selected. 

如果ID2不需要与ID1相关,则您可以根据需要订购:

merge into table1
using (
  select name, dob, id1,
    100 + dense_rank() over (order by name, dob)
        + dense_rank() over (partition by name, dob order by id1)/10
        as id2
  from table1
) tmp on (tmp.id1 = table1.id1)
when matched then
update set table1.id2 = tmp.id2;

select * from table1;

NAME  DOB               ID1        ID2
----- ---------- ---------- ----------
JIM   1991-11-30       23.1      102.1
JIM   1991-11-30       23.2      102.2
JIM   1991-11-30       23.3      102.3
TOM   1993-12-30       30.1      103.1
TOM   1993-12-30       30.2      103.2
HENRY 1994-12-03       34.1      101.1
HENRY 1994-12-03       34.2      101.2
只有在小数部分不超过0.9的情况下,它才会按原样工作;但如果是这样的话,就很难解释这些值(因为23.10和23.1是一样的)

我还假设,我想,这是一次一次性的更新,您不打算在将来的插入中使用序列;目前还不清楚您将如何管理它-如果名称/DOB不存在,您只想获取下一个序列值,如果名称/DOB不存在,则需要查找现有的最高ID并向其添加0.1。无论哪种方式,您都必须序列化插入以防止冲突或差异

它实际上进入了一种情况,ID1的值是23.10,23.11,ID2的值是101.1101.1。
... 我试着将它除以100,对于值>=.11小数位,问题得到了解决,但对于.10和.20,它仍然显示为.1和.2

这表明两个ID值都是字符串而不是数字。如果是这样,您仍然可以使用排名函数,但将生成的两个数字视为字符串,并将它们连接在一起:

    merge into table1
    using (
      select name, dob, id1,
        to_char(100 + dense_rank() over (order by name, dob))
            ||'.'||
            dense_rank() over (partition by name, dob
              order by to_number(substr(id1, instr(id1, '.') + 1)))
            as id2
      from table1
    ) tmp on (tmp.id1 = table1.id1)
    when matched then
    update set table1.id2 = tmp.id2;

With some additional base data that gives you:

select * from table1;

NAME  DOB        ID1        ID2       
----- ---------- ---------- ----------
JIM   1991-11-30 23.1       103.1     
JIM   1991-11-30 23.2       103.2     
JIM   1991-11-30 23.3       103.3     
TOM   1993-12-30 30.1       104.1     
TOM   1993-12-30 30.3       104.2     
HENRY 1993-12-30 34.1       101.1     
HENRY 1994-12-03 34.5       102.1     
HENRY 1994-12-03 34.6       102.2     
HENRY 1994-12-03 34.7       102.3     
HENRY 1994-12-03 34.8       102.4     
HENRY 1994-12-03 34.9       102.5     
HENRY 1994-12-03 34.10      102.6     
HENRY 1994-12-03 34.11      102.7     
HENRY 1994-12-03 34.12      102.8     
HENRY 1994-12-03 34.13      102.9     
HENRY 1994-12-03 34.14      102.10    
HENRY 1994-12-03 34.15      102.11    
HENRY 1994-12-03 34.16      102.12    


当然,这样做不可能让我们很尴尬地将ID2值视为数字或以有意义的方式对它们进行排序;但对于ID1值来说,情况肯定已经是这样了。另一种方法可能是将第一部分乘以一个大的数字,比如1000,然后再加上第二部分——因此Henry的结果是1020001到1010012。

您计划在以后的插入中使用该序列,还是仅用于此一次性更新?如果是将来,您将如何处理.1/.2/.3部分?(为什么名称/DOB首先是重复的?)另外,ID2值的顺序应该与ID1值的顺序相匹配,还是应该是独立的并由其他东西排序?嗨,这只是一次性的过程。为什么会有重复的名称和dob?这就是数据的结构。ID2可以是任何顺序,它不需要与ID1匹配感谢Alex提供上述解决方案,但在我的情况下,ID1的顺序与ID2不匹配。在这种情况下,你建议我怎么做?在你的例子中,他们似乎是匹配的;但是您可以在/both
densite\u rank()
调用中更改顺序。我已经添加了一个按名称/DOB排序的示例。如果你有一个规则来说明它们应该如何排序,并且无法调整此解决方案以匹配你的规则,那么你需要解释它。哇,这是一个令人惊讶的解决方案,但是的,它实际上进入了一个ID1值为23.10,23.11,ID2显示为101.1,101.1的情况。在这种情况下,您建议我怎么做?我尝试将它除以100,对于值>=.11小数位,问题得到解决,但对于.10和.20,它仍然显示为.1和.2。尽管如此,我还是对解决方案感到满意:)所以它们是字符串而不是数字?ID2也是字符串吗?您可以在句点之后附加ID1字符串的部分,而不是计算新的数字。