如何复制记录,修改并将它们添加到同一表中

时间:2019-04-15 13:29:56

标签: sql sql-server temp-tables

我有一个问题,希望您能帮助我。 :)

我有一张像这样的桌子:

ID  Col1        Col2        ReverseID
1   Number 1    Number A    
2   Number 2    Number B    
3   Number 3    Number C    

我想要实现的是:

  • 使用切换的列为每个记录创建重复项,并将它们添加到原始表中
  • 将重复项的ID添加到原始记录的ReverseID列中,反之亦然

因此新表应如下所示:

ID  Col1        Col2        ReverseID
1   Number 1    Number A    4
2   Number 2    Number B    5
3   Number 3    Number C    6
4   Number A    Number 1    1
5   Number B    Number 2    2
6   Number C    Number 3    3

到目前为止,我所做的是使用临时表:

SELECT * INTO #tbl
FROM myTable

UPDATE #tbl
SET Col1 = Col2,
    Col2 = Col1,
    ReverseID = ID

INSERT INTO DUPLICATEtable(
        Col1,
        Col2,
        ReverseID
)

SELECT Col1,
       Col2,
       ReverseID
FROM #tbl

在此示例代码中,我使用了辅助表只是为了确保我不会破坏原始数据记录。

我想我可以跳过SET部分并更改最后一个SELECT语句中的列以实现相同功能,但是我不确定。

无论如何-这样我最终会到达:

ID  Col1        Col2        ReverseID
1   Number 1    Number A    
2   Number 2    Number B    
3   Number 3    Number C    
4   Number A    Number 1    1
5   Number B    Number 2    2
6   Number C    Number 3    3

所以问题仍然存在:如何将ReverseIDs正确添加到原始记录中?

我几乎可以肯定,因为我的SQL知识还很低,所以这不是最简单的处理方式,所以希望大家对我有所启发,并为我提供一个更优雅的解决方案。

提前谢谢!

br 捷运

编辑:

我试图说明我最初的问题,所以这篇文章过长。 ;)

ED

首先:我的前端不允许使用任何SQL语句,我必须专注于类,属性,关系。

第一个根本原因: 类B的实例(B1,B2,B3等)在类Relation中链接在一起,它们是同一类的多对多关系。我的前端不允许连接表,所以这是一种解决方法。

统计用户身份时,会添加一个关系,其中B1作为第一面(我称之为“左”),而B2作为第二面(右):

从B1导航,将显示两个关系(FK_Left,FK_Right),但是只有其中一个包含一个值(比方说FK_Left)。

从B2导航,该值将仅在其他关系(FK_Right)中列出。 因此,从用户的角度来看,总是显示两个关系,但是这取决于记录的输入方式(如果一个人可以在relationship_left或relationship_right之后找到数据)。 那不是实际的可用性。

如果我拥有所有记录,反之亦然,那么我可以隐藏其中一个关系,并且用户可以看到一个关系背后的所有信息,而不论其输入方式如何。

第二个根本原因: 前端提供一些矩阵视图,该视图将关系类作为输入,并在列中显示左伙伴,在行中显示右伙伴。

假设我要在列中看到A的所有实例,在行中看到它们的伙伴,这只有在以相同方式(例如,所有A实例均作为左伙伴。

关于行和列的矩阵视图应该可以自由过滤,因此,如果我有重复关系,则可以对行和列中的任何伙伴进行过滤。

很抱歉,我的情况很清楚。

3 个答案:

答案 0 :(得分:1)

这种事情的窍门是从获取所需数据的SELECT开始。在这种情况下,您需要一个具有Col1,Col2,reverseid的结果集。

SELECT Col2 Col1, Col1 Col1, ID reverseid
  INTO #tmp   FROM myTable;

说服自己是正确的-交换了列值等。

然后执行以下操作:

INSERT INTO myTable (Col1, col2, reverseid)
SELECT Col1, Col2, reverseid FROM #tmp;

如果您是通过ssms之类的GUI执行此操作的,请不要忘记DROP TABLE #tmp;

但是,您可以通过纯查询获得相同的结果,而无需重复行。为什么要这样呢?

  1. 您可以为反向行节省浪费的空间。
  2. 即使您忘记运行将其反转并将其插入到表中的过程,也总是获得到最后一秒的反转行。
  3. 如果您从表中插入或删除行,则不会出现一致性问题。

这是您可能的操作方式。

 SELECT Col1, Col2, null reverseid FROM myTable
  UNION ALL
 SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;

您甚至可以将其放入视图并像使用向前的表一样使用它。

CREATE VIEW myTableWithReversals AS
SELECT Col1, Col2, null reverseid FROM myTable
 UNION ALL
SELECT Col2 Col1, Col1 Col2, ID reverseid FROM myTable;

然后您可以说SELECT * FROM myTableWithReversals WHERE Col1 = 'value'等。

答案 1 :(得分:1)

我建议仅使用视图,而不要尝试创建和维护相同数据的两个副本。然后,您只需从视图中选择而不是基础表即可。

create view MyReversedDataView as

select ID
    , Col1
    , Col2
from MyTable

UNION ALL

select ID
    , Col2
    , Col1
from MyTable

答案 2 :(得分:1)

让我假设id列是自动递增的。然后,您可以分两个步骤进行操作:

insert into myTable (Col1, Col2, reverseid)
    select col2, col1, id
    from myTable t
    order by id;  -- ensures that they go in in the right order

这将在右侧插入reverseid的新ID。现在我们必须更新以前的值:

update t
    set reverseid = tr.id
    from myTable t join
         myTable tr
         on tr.reverseid = t.id;

请注意,不需要临时表。