Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.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 在保持id连续性的同时从数据库中删除行_Sql_Sql Server_Oracle - Fatal编程技术网

Sql 在保持id连续性的同时从数据库中删除行

Sql 在保持id连续性的同时从数据库中删除行,sql,sql-server,oracle,Sql,Sql Server,Oracle,我有一个表,有10行,ID为1-10。我想删除第5行和第8行,我想更新ID,使其为1-8,而不是1-4、6-7和9-10。我不想运行大量的update语句,也不想手工操作。我还需要同时适用于SQLServer和Oracle数据库的解决方案。我认为像过程这样的东西可以做到这一点,但我不知道如何创建一个或如何进行。在Oracle中,这很简单-您只需使用MERGE语句和行数分析函数,如下所示: drop table test1; create table test1 as select level

我有一个表,有10行,ID为1-10。我想删除第5行和第8行,我想更新ID,使其为1-8,而不是1-4、6-7和9-10。我不想运行大量的update语句,也不想手工操作。我还需要同时适用于SQLServer和Oracle数据库的解决方案。我认为像过程这样的东西可以做到这一点,但我不知道如何创建一个或如何进行。在Oracle中,这很简单-您只需使用MERGE语句和行数分析函数,如下所示:

drop table test1;

create table test1
as
select level id,
       level some_val
from   dual
connect by level <= 10;

delete from test1
where id in (5, 8);

merge into test1 tgt
using (select rowid row_id,
              id,
              row_number() over (order by id) rn
       from   test1) src
  on (tgt.rowid = src.row_id)
when matched then
update set tgt.id = src.rn;

commit;

select * from test1;

        ID   SOME_VAL
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          6
         6          7
         7          9
         8         10

ETA:我会回应其他人关于为什么需要这样做的说法,尤其是如果id列是主键,并且有外键引用它

在Oracle中,这很简单-您只需使用MERGE语句和行数分析函数,如下所示:

drop table test1;

create table test1
as
select level id,
       level some_val
from   dual
connect by level <= 10;

delete from test1
where id in (5, 8);

merge into test1 tgt
using (select rowid row_id,
              id,
              row_number() over (order by id) rn
       from   test1) src
  on (tgt.rowid = src.row_id)
when matched then
update set tgt.id = src.rn;

commit;

select * from test1;

        ID   SOME_VAL
---------- ----------
         1          1
         2          2
         3          3
         4          4
         5          6
         6          7
         7          9
         8         10

ETA:我会回应其他人关于为什么需要这样做的说法,尤其是如果id列是主键,并且有外键引用它

正如戈登·林诺夫指出的那样,你真的不应该那样做。如果您仍然愿意这样做,下面是一个更新:

只要允许更新主键,该语法可能在Oracle和仅在Oracle中测试的MSSQL中都可以使用。
尽管如此,我还是建议不要使用这种技术。如果您想要一个连续的整数列,请使用上面查询中使用的row_number动态生成一个。

正如Gordon Linoff指出的,您确实不应该这样做。如果您仍然愿意这样做,下面是一个更新:

只要允许更新主键,该语法可能在Oracle和仅在Oracle中测试的MSSQL中都可以使用。
尽管如此,我还是建议不要使用这种技术。如果您想要一个连续的整数列,请使用上面查询中使用的行号来动态生成一个列。

您应该包括您尝试过的内容,无论如何,您可以运行此查询,直到不再发生更新,如果您不关心性能,请按id更好地排序,并像其他答案一样使用行号:

UPDATE myTable t SET id = id - 1 WHERE id <> 1 AND
   NOT EXISTS (SELECT * FROM myTable s WHERE s.id = t.id - 1)

您应该包括您尝试过的内容,无论如何,您可以运行此查询,直到不再发生更新(如果您不关心性能)、更好地按id排序并像其他答案一样使用行号:

UPDATE myTable t SET id = id - 1 WHERE id <> 1 AND
   NOT EXISTS (SELECT * FROM myTable s WHERE s.id = t.id - 1)


除非你有一个非常非常好的理由,否则你不应该关心自动生成的id的具体值。漏洞对于数据库来说不是问题。为什么要求保持id连续性?出于OCD原因。此外,id不是自动生成的,它是一个手工制作的不可编辑的表,包含静态业务逻辑数据。id列是否有来自引用它的其他表的外键?因为如果是这样的话,强迫症的原因并不是进行此更新的有效原因。强迫症的原因是从事任何工作的可怕原因,除非你自己支付工资。除非你有非常非常好的理由,您不应该关心自动生成的id的具体值是多少。对于数据库来说,孔不是问题。为什么要求保持id连续性?出于OCD原因。此外,id不是自动生成的,它是一个手工制作的不可编辑的表,包含静态业务逻辑数据。id列是否有来自引用它的其他表的外键?因为如果是这样,OCD原因就不是进行此更新的有效原因。OCD原因是从事任何工作的可怕原因,除非您自己支付工资。唯一的问题是,在Oracle中,您不能更新合并中属于加入条件的列,因此,您的merge语句将导致“ORA-38104:ON子句中引用的列无法更新:T.PRIMARY_KEY”。@Boneist感谢您指出这一点。将其更改为更新。唯一的问题是,在Oracle中,您无法更新合并中属于联接条件一部分的列,因此您的merge语句将导致“ORA-38104:ON子句中引用的列无法更新:t.PRIMARY_KEY”。@Boneist感谢您指出这一点。将其更改为更新。这不起作用;它给您留下了ID 1-5、7-8和10,这不是OP想要的。@Boneist在nore更新发生之前不会真正重复,要查看在PL/SQL中是如何完成的,最多需要30秒的搜索时间,所以我没有显示它。我也知道这不好,这就是为什么我对其他答案投了更高的票,但这仍然是一个解决方案。啊,我错过了那一步。但是OP不想运行多个update语句,所以…@Boneist我想在惰性的意义上使用多个update语句。。。插入到。。。插入到。。。但这实际上听起来相当愚蠢,因为他甚至提到手动操作,这对他来说可能已经是一个进步了;它给您留下了ID 1-5、7-8和10,这不是OP想要的。@Boneist在nore更新发生之前不会真正重复,要在PL/SQL中查看这是如何完成的,最长需要30秒的搜索时间,所以
我没有表现出来。我也知道这不好,这就是为什么我对其他答案投了更高的票,但这仍然是一个解决方案。啊,我错过了那一步。但是OP不想运行多个update语句,所以…@Boneist我想在惰性的意义上使用多个update语句。。。插入到。。。插入到。。。但这实际上听起来相当愚蠢,因为他甚至提到手动操作,这对他来说可能已经是一个进步。