【发布时间】:2011-10-21 05:30:30
【问题描述】:
我想在 SQL Server 表的特定位置插入一行。例如,我的表有 100 行,我想在位置 9 插入一个新行。但是表的 PK 的 ID 列已经有一个 ID 为 9 的行。我怎样才能在这个位置插入一行,以便所有移动到下一个位置后的行?
【问题讨论】:
标签: sql sql-server insert rows
我想在 SQL Server 表的特定位置插入一行。例如,我的表有 100 行,我想在位置 9 插入一个新行。但是表的 PK 的 ID 列已经有一个 ID 为 9 的行。我怎样才能在这个位置插入一行,以便所有移动到下一个位置后的行?
【问题讨论】:
标签: sql sql-server insert rows
不,您无法控制新行的插入位置。实际上,您不需要:在您的 SELECT 语句中使用 ORDER BY 子句以您需要的方式对结果进行排序。
【讨论】:
关系表没有“位置”。作为优化,索引将按指定键对行进行排序,如果您希望在键顺序中以特定排名插入行,请使用在该排名位置排序的键插入它。在您的情况下,如果 ID 大于 8,则必须使用值更新所有行以将 ID 增加 1,然后插入值为 9 的 ID:
UPDATE TABLE table SET ID += 1 WHERE ID >= 9;
INSERT INTO TABLE (ID, ...) VALUES (9, ...);
不用说,做这样的事情不可能有任何理智的理由。如果您真的有这样的要求,那么您将使用具有两个(或更多)部分的复合键。这样的键将允许您插入子键,以便按所需顺序排序。但是更有可能您的问题可以通过指定正确的 ORDER BY 来专门解决,而不会弄乱行的物理顺序。
另一种看待它的方式是重新考虑主键的含义:实体的标识符,在实体生命周期内不会改变。然后,您的问题可以改写为使您的问题中的谬误更加明显:
我想将 ID 为 9 的实体的内容更改为一些新的 价值。实体 9 的旧值应移至内容 ID 为 10 的实体。 ID 为 10 的实体的旧内容应为 移动到 ID 为 11 的实体...等等。老人 具有最高 ID 的实体的内容应作为新插入 实体。
【讨论】:
通常您不希望以这种方式使用主键。 更好的方法 是创建另一个名为“位置”或类似的列,您可以在其中跟踪您自己的订购系统。
要执行转换,您可以运行如下查询:
UPDATE table SET id = id + 1 WHERE id >= 9
如果您的列使用 auto_increment 功能,这将不起作用。
【讨论】:
这种方式违背了关系表的目的,但如果你需要,其实也不是那么难做到。
1) 使用ROW_NUMBER() OVER(ORDER BY NameOfColumnToSort ASC) AS Row 为表格中的行号创建一列。
2) 从这里您可以使用 WHERE Row < ## 和 @987654324 将表的前后部分复制(使用 SELECT columnsYouNeed INTO )到两个单独的表中(基于要在其后插入值的行号)分别@声明。
3) 接下来使用DROP TABLE 删除原始表。
4) 然后你使用UNION 用于前表、要插入的行(使用单个显式定义的SELECT 语句,没有其他任何内容)和后表。到目前为止,您有两个 UNION 语句用于 3 个单独的选择子句。在这里,您可以将其包装在 SELECT INTO FROM 子句中,将其称为原始表的名称。
5) 最后,你 DROP TABLE 你制作的两张桌子。
这类似于ALTER TABLE 的工作方式。
【讨论】:
INSERT INTO customers
(customer_id, last_name, first_name)
SELECT employee_number AS customer_id, last_name, first_name
FROM employees
WHERE employee_number < 1003;
【讨论】:
DECLARE @duplicateTable4 TABLE (id int,data VARCHAR(20))
INSERT INTO @duplicateTable4 VALUES (1,'not duplicate row')
INSERT INTO @duplicateTable4 VALUES (2,'duplicate row')
INSERT INTO @duplicateTable4 VALUES (3,'duplicate rows')
INSERT INTO @duplicateTable4 VALUES (4,'second duplicate row')
INSERT INTO @duplicateTable4 VALUES (5,'second duplicat rows')
DECLARE @duplicateTable5 TABLE (id int,data VARCHAR(20))
insert into @duplicateTable5 select *from @duplicateTable4
delete from @duplicateTable4
declare @i int , @cnt int
set @i=1
set @cnt=(select count(*) from @duplicateTable5)
while(@i<=@cnt)
begin
if @i=1
begin
insert into @duplicateTable4(id,data) select 11,'indian'
insert into @duplicateTable4(id,data) select id,data from @duplicateTable5 where id=@i
end
else
insert into @duplicateTable4(id,data) select id,data from @duplicateTable5 where id=@i
set @i=@i+1
end
select *from @duplicateTable4
【讨论】: