Sql server 在SQL中,使用映射表将值从一列复制到另一列(相同的表)
我试图将值从同一个表中的一列复制到另一列,并努力找出正确的方法。 理想情况下,我会在代码中而不是在SQL中这样做,但是我处理的是一个遗留应用程序,因此更新代码(新版本已经在开发中)是不可能的 我有下表(Sql server 在SQL中,使用映射表将值从一列复制到另一列(相同的表),sql-server,tsql,sql-server-2012,Sql Server,Tsql,Sql Server 2012,我试图将值从同一个表中的一列复制到另一列,并努力找出正确的方法。 理想情况下,我会在代码中而不是在SQL中这样做,但是我处理的是一个遗留应用程序,因此更新代码(新版本已经在开发中)是不可能的 我有下表(IncomingData) 因此,我们将: id SourceID QuestionnaireID Q1 Q2 Q3 Q4 Q5 1 5000 10 1 2 1 5 3
IncomingData
)
因此,我们将:
id SourceID QuestionnaireID Q1 Q2 Q3 Q4 Q5
1 5000 10 1 2 1 5 3
数据偶尔会(通过Web服务)从特定的SourceID
,其中Q1(etc)需要移动到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) 数据出现在收入数据中
2) 计划运行从incomingdata
id PK
SourceID int
QuestionnaireID int
Q1 varchar(500)
Q2 varchar(500)
..
..
Q50 varchar(500)
3) 在存储过程中运行一个函数,该函数将SourceID
和QuestionnaireID
作为参数,并搜索SourceDestXmap
表
4) 如果存在匹配项(即某些列需要更改),则对于SourceDestXmap
中的每一行,SourceQ
的值需要插入到临时表的DestQ
中
因此,从上面的示例来看,IncomingData.Q5的值需要插入tempData.Q8列,在该列中,映射是从SourceDestXmap
注意事项:
可以有任意数量的映射,例如问题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
当然,这并不完全是你所需要的(我不完全理解),但你可能会有一个想法,如何在一个步骤中“转移”你的价值观并设置新的价值观(更新):
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
我不知道我是否完全理解你的问题,但是你能使用触发器来更新另一列吗?嗯,你的表设计是-uhm-ehm-uhm-可改进的…:-)“你有没有机会改变那里的东西,或者你必须坚持这个结构?”杰瑞米我确实考虑了触发器,但最终,一旦Q3移动到Q5,那么我就失去了原来的Q5的价值。这就是为什么我在考虑创建一个临时表并将值放入其中会很好。如果您的问题不是保留刚刚覆盖的值,您可以从头到脚地执行此操作?将Q5复制到Q8,而将Q4复制到Q7等等…@Shnugo是的,
incomingdata
的表设计是。。。有趣的。。。(不是我的设计)但遗憾的是不可更新。映射表的结构是可变的。谢谢,但我不太确定这是我想要的。请问newdata
的值来自哪里?它们-应该-与Incomingdata的值相同,只是输入到映射表中指定的列中。也许我需要更好地解释我的问题…@kolin,好吧,对于这个问题,你可以使用更新或插入触发器,甚至可能使用替代触发器。在此触发器中,您可以使用伪表“inserted”代替“newData”。另一种方法是定义一个StoredProcess来执行insert/update,它将您的值作为参数,并逐行调用它。。。