【问题标题】:How to Insert a new record in the middle of any table如何在任何表的中间插入新记录
【发布时间】:2016-07-14 21:33:16
【问题描述】:

我想在 SQL Server 表的特定位置插入一行。例如,我的表有 100 行,并且我有一个名为 LineNumber 的字段,我想在第 9 行之后插入一个新行。但是表的 PK 的 ID 列已经有一行 LineNumber 9。所以现在我需要行号为 9 或 10 的新行,以便 ID 字段必须自动更新。我怎样才能在这个位置插入一行,以便它之后的所有行都移动到下一个位置?

【问题讨论】:

  • 表格本质上是未排序的,因此您不能在“中间”插入记录。你能改写你的问题吗?
  • 这只是一次性交易还是您需要定期做的事情?
  • 你不插入一个位置,你按照你需要的顺序读出,并且有一个可以用于排序的字段。在您的情况下,如果您想随着时间的推移更改事物的顺序,请不要使用主键。
  • 好像是stackoverflow.com/questions/6962867/…的重复问题
  • 将 PK 用于唯一标识行之外的任何其他内容是一种非常糟糕的做法。如果您需要一个排序列,请添加一个。

标签: sql-server


【解决方案1】:

不要修改主键,因为您有要插入的新记录,所以这不是修改输出顺序的好方法。

在表格上添加一个新列来保存您的订单。然后,您可以将主键值复制到该列(如果这是您当前的顺序),然​​后再对新行进行所需的更改。

您应该能够复制和粘贴并按原样运行的示例:

我添加了orderid 列,您需要使用默认空值来处理。

DECLARE @OrderTable AS TABLE
    (
      id INT ,
      val VARCHAR(5) ,
      orderid INT
    )

INSERT  INTO @OrderTable
        ( id, val, orderid )
VALUES  ( 1, 'aaa', NULL )
        ,
        ( 2, 'bbb', NULL )
        ,
        ( 3, 'ddd', NULL )

SELECT  *
FROM    @OrderTable

-- Produces:
/*
id  val orderid
1   aaa NULL
2   bbb NULL
3   ddd NULL
*/

-- Update the `orderid` column to your existing order:

UPDATE  @OrderTable
SET     orderid = id

SELECT  *
FROM    @OrderTable

-- Produces:
/*
id  val orderid
1   aaa 1
2   bbb 2
3   ddd 3
*/

-- Then you want to add a new item to change the order:

DECLARE @newVal AS NVARCHAR(5) = 'ccc'
DECLARE @newValOrder AS INT = 3

-- Update the table to prepare for the new row:

UPDATE  @OrderTable
SET     orderid = orderid + 1
WHERE   orderid >= 3

-- this inserts ID = 4, which is what your primary key would do by default
-- this is just an example with hard coded value
INSERT  INTO @OrderTable
        ( id, val, orderid )
VALUES  ( 4, @newVal, @newValOrder )

-- Select the data, using the new order column:

SELECT  *
FROM    @OrderTable
ORDER BY orderid 

-- Produces:
/*
id  val orderid
1   aaa 1
2   bbb 2
4   ccc 3
3   ddd 4
*/

【讨论】:

    【解决方案2】:

    使这变得困难的是该列是主键。如果您可以在没有其他人的情况下与数据库进行交互,那么您可以这样做:

    • 使列不再是主键。
    • 运行如下命令:
    UPDATE MyTable
        SET PrimaryColumnID = PrimaryColumnID + 1
    WHERE PrimaryColumnID > 8
    
    • 插入具有适当 PrimaryColumnID (9) 的行。
    • 将该列恢复为主键。

    显然,这可能不适用于一张大桌子。您可以创建一个新的主键列并对其进行切换,然后修复值,然后将其切换回来。

    【讨论】:

    • 简单地“使列不再是主键”不是一个好建议,很多事情都可能依赖于主键,那么对于引用链接表中的主键的任何事情,你会怎么做?
    • @Tanner 只是一会儿。当然,我假设该表可以单独使用。
    • @tanner 你从来没有在测试数据库中做过这个吗?我当然有。您为 50 个州制作了一个表格,然后意识到您没有完全按字母顺序排列它们,因此您删除了主键,重新编号,然后重新添加主键。然后当您复制到 live 时,它​​的顺序是正确的.
    • 您是否也更新了该表的所有具有外键的数据?为了扩展您的示例,如果有一个县表。这现在指向不正确的状态。
    • 为什么美国各州的表格需要一个身份?状态码是一个完全可靠的主键。
    【解决方案3】:

    两步,先更新LineNumber

    UPDATE
        table
    SET
        LineNumber = LineNumber + 1
    WHERE
        LineNumber>9
    

    然后插入

    INSERT INTO table
    (LineNumber, ...) VALUES (10, .....)
    

    【讨论】:

    • OP 声明此字段是主键,因此这将无法正常工作,因为 10 可能已经被占用了
    • 我同意使用主键进行订购是不好的设计
    猜你喜欢
    • 2012-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 2015-08-14
    相关资源
    最近更新 更多