【问题标题】:Copy value from one column to another (same table) in SQL using a mapping table使用映射表在 SQL 中将值从一列复制到另一列(同一张表)
【发布时间】:2016-01-11 23:28:35
【问题描述】:

我试图在同一个表中将值从一列复制到另一列,并努力找出正确的方法来做到这一点。 理想情况下,我会在代码中而不是 SQL 中执行此操作,但是我正在处理遗留应用程序,因此更新代码(虽然新版本已经在开发中)是不行的。

我有下表 (IncomingData)

id PK
SourceID int
QuestionnaireID int
Q1 varchar(500)
Q2 varchar(500)
..
..
Q50 varchar(500)

所以我们会:

id    SourceID    QuestionnaireID    Q1    Q2    Q3    Q4    Q5
1     5000        10                 1     2     1     5     3

数据偶尔会从特定的SourceID 进入(通过网络服务),Q1(等)需要移动到 Q3 以便我们的系统正确处理它。 所以为此我创建了如下映射表

id    SourceID    QuestionnaireID    SourceQ    DestQ
1     5000        10                 Q1         Q3
1     5000        10                 Q2         Q4
1     5000        10                 Q3         Q5
1     5000        10                 Q4         Q7
1     5000        10                 Q5         Q8

我的想法是创建一个与IncomingData 匹配的临时表,将值复制到此临时表中的正确列,然后使用正确列中的值更新该行的IncomingData

有没有一种简单的方法可以做到这一点?我唯一能看到的就是在这个函数中创建许多动态 SQL 语句并执行它们。由于注入,这让我很担心,但是插入临时表的 sql 只能从映射表创建,因此外部变量不会传递给动态 SQL,所以这会是一个问题吗?

更新

其中的(我预期的)数据流:

1) 数据出现在IncomingData

2) 计划运行一个存储过程,从incomingdata 获取数据

3) 函数在存储过程中运行,以SourceIDQuestionnaireID 作为参数并搜索SourceDestXmap

4) 如果存在匹配项(即某些列需要更改),那么对于SourceDestXmap 中的每一行,SourceQ 的值需要插入到临时表的DestQ 中。

所以从上面的例子来看,IncomingData.Q5 的值需要插入到 tempData.Q8 列中,其中映射是从SourceDestXmap 计算出来的

注意事项: 可能存在任意数量的映射,例如 QuestionnaireID 11 可能具有 Q8->Q27 映射以及 Q16->Q4 映射。

更新 #2

我基本上需要一种更动态的方式来做这样的事情:

BEGIN
            DECLARE @tmpQ3 varchar(2000) 
            DECLARE @tmpQ4 varchar(2000) 
            DECLARE @tmpQ5 varchar(2000) 
            DECLARE @tmpQ7 varchar(2000) 
            DECLARE @tmpQ8 varchar(2000) 

            SET @tmpQ3 = @prmQ1
            SET @tmpQ4 = @prmQ2
            SET @tmpQ5 = @prmQ3
            SET @tmpQ7 = @prmQ4
            SET @tmpQ8 = @prmQ5

            SET @prmQ1 = NULL
            SET @prmQ2 = NULL
            SET @prmQ3 = NULL
            SET @prmQ4 = NULL
            SET @prmQ5 = NULL

            SET @prmQ3 = @tmpQ3
            SET @prmQ4 = @tmpQ4
            SET @prmQ5 = @tmpQ5
            SET @prmQ7 = @tmpQ7
            SET @prmQ8 = @tmpQ8
        END

【问题讨论】:

  • 我不知道我是否完全理解您的问题,但是您可以使用触发器来更新另一列吗?
  • 嗯,你的桌子设计是 - 嗯 - 嗯 - 嗯 - 可以改进... :-) 你有机会改变那里的东西还是你必须坚持这种结构?
  • @Jeremy 我确实考虑过触发器,但最终,一旦将 Q3 移至 Q5,我就失去了原始 Q5 的价值。这就是为什么我想创建一个临时表并将值放在那里会很好。
  • 如果您的问题不是要保留刚刚覆盖的值,您可能只是前后来回执行此操作?将 Q5 复制到 Q8,然后将 Q4 复制到 Q7 等等......
  • @Shnugo 是的,incomingdata 的表格设计...很有趣...(不是我的设计)但遗憾的是不可更新。映射表的结构是可变的。

标签: sql-server tsql sql-server-2012


【解决方案1】:

当然,这不完全是您所需要的(我并不完全理解它——实际上),但您可能会想到,如何将您的价值观“转移”到一边,并在一个步骤中设置新值(更新):

DECLARE @IncomingData TABLE(ID INT,SourceID INT,QuestionairID INT,Q1 VARCHAR(10),Q2 VARCHAR(10),Q3 VARCHAR(10),Q4 VARCHAR(10),Q5 VARCHAR(10));
INSERT INTO @IncomingData VALUES (1,5000,10,'1','2','3','4','5');

DECLARE @NewData TABLE(ID INT,SourceID INT,QuestionairID INT,Q1 VARCHAR(10),Q2 VARCHAR(10),Q3 VARCHAR(10),Q4 VARCHAR(10),Q5 VARCHAR(10));
INSERT INTO @NewData VALUES (1,5000,10,'new1','new2','new3','new4','new5');

--This will shift all original data "two steps aside"...

UPDATE @IncomingData SET id.Q5=id.Q3,id.Q4=id.Q2,id.Q3=id.Q1
                        ,id.Q2=new.Q2
                        ,id.Q1=new.Q1
FROM @IncomingData AS id
CROSS JOIN @NewData AS new

SELECT * FROM @IncomingData

结果:

ID  SourceID    QuestionairID   Q1      Q2      Q3  Q4  Q5
1   5000        10              new1    new2    1   2   3

【讨论】:

  • 谢谢,但我不太确定这是我想要的。请问newdata 的值是从哪里来的?它们 - 应该 - 与 Incomingdata 的值相同,只是输入到映射表中指定的列中。也许我需要更好地解释我的问题......
  • @kolin,好的,为此您可以使用 UPDATE 或 INSERT 触发器,甚至可以使用 INSTEAD OF 触发器。在此触发器中,您可以使用伪表“插入”代替“newData”。另一种方法是定义一个 StoredProcedure 来执行插入/更新,它将您的值作为参数并逐行调用它...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多