我有一个select语句,我想将其转换为表中名称为Variable[N]
的所有列的更新语句。
例如,我想做这些事情:
n
个列,其名称为variable[N]
。以下示例仅更新列variable63
,但我想在名称为variable1
到variableN
的所有列上动态运行更新,而不知道我提前有多少variable[N]
列。此外,在下面的示例中,我将更新的结果导入NewCol
。我实际上想要在可能的情况下使用结果更新相应的变量列,variable63
在我的示例中。我希望有一个包装器循环遍历variable1
列到variableN
,并对所有这些列执行相同的更新操作:
SELECT
projectid
,documentid
,revisionno
,configurationid
,variable63
,ISNULL(Variable63,
(SELECT TOP 1
variable63
FROM table1
WHERE
documentid = t.documentid
and projectid=t.projectid
and configurationid=t.configurationid
and cast(revisionno as int) < cast(t.revisionno as int)
AND Variable63 is NOT NULL
ORDER BY
projectid desc
,documentid desc
,revisionno desc
,configurationid desc
)) as NewCol
FROM table1 t;
答案 0 :(得分:0)
没有通用的方法来循环SQL中的变量,你应该知道你想要修改的内容。在某些数据库中,可以查询系统表以动态构建更新语句(我知道如何在InterBase中执行此操作并且它是狡猾的Firebird),但您还没有告诉我们您正在使用哪个数据库引擎。 / p>
下面是一种可以更新多个null字段的方法,COALESCE和CASE是做同样事情的两种方式,就像使用LEFT JOIN或NOT EXISTS一样。使用您和您的数据库引擎最适合的那些。请注意所有记录都将被更新,因此如果您的数据库包含数百万条记录,每条记录都很大并且您希望此查询执行很多次,这不是一个好的解决方案。
UPDATE table1 t
SET t.VARIABLE63 =
COALESCE(t.VARIABLE63,
(SELECT VARIABLE63
FROM table1 t0
LEFT JOIN table1 tNot
ON tNot.documentid = t.documentid
AND tNot.projectid=t.projectid
AND tNot.configurationid=t.configurationid
AND cast(tNot.revisionno as int) > cast(t0.revisionno as int)
AND cast(tNot.revisionno as int) < cast(t.revisionno as int)
AND tNot.Variable63 is NOT NULL
WHERE t0.documentid = t.documentid
AND t0.projectid=t.projectid
AND t0.configurationid=t.configurationid
AND cast(t0.revisionno as int) < cast(t.revisionno as int)
AND t0.Variable63 is NOT NULL
AND tNot.Variable63 is NULL)),
t.VARIABLE64 = CASE WHEN t.VARIABLE64 IS NOT NULL then t.VARIABLE64
ELSE (SELECT VARIABLE64
FROM table1 t0
WHERE t0.documentid = t.documentid
AND t0.projectid=t.projectid
AND t0.configurationid=t.configurationid
AND cast(t0.revisionno as int) < cast(t.revisionno as int)
AND t0.Variable64 is NOT NULL
AND NOT EXISTS(SELECT 1
FROM table1 tNot
WHERE tNot.documentid = t.documentid
AND tNot.projectid=t.projectid
AND tNot.configurationid=t.configurationid
AND cast(tNot.revisionno as int) > cast(t0.revisionno as int)
AND cast(tNot.revisionno as int) < cast(t.revisionno as int)
AND tNot.Variable64 is NOT NULL)) END
答案 1 :(得分:0)
好吧,我想我明白了。循环遍历列并在每列上运行更新命令的函数。
DECLARE @sql NVARCHAR(1000),
@cn NVARCHAR(1000)--,
--@r NVARCHAR(1000),
--@start INT
DECLARE col_names CURSOR FOR
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'PIVOT_TABLE'
ORDER BY ordinal_position
--SET @start = 0
DECLARE @op VARCHAR(max)
SET @op=''
OPEN col_names FETCH next FROM col_names INTO @cn
WHILE @@FETCH_STATUS = 0
BEGIN
--print @cn
IF UPPER(@cn)<> 'DOCUMENTID' and UPPER(@cn)<> 'CONFIGURATIONID' and UPPER(@cn)<> 'PROJECTID' and UPPER(@cn)<> 'REVISIONNO'
BEGIN
SET @sql = 'UPdate pt
set pt.' + @cn + ' = ((SELECT TOP 1 t.' + @cn + ' FROM pivot_table t WHERE t.documentid = pt.documentid and t.projectid=pt.projectid
and t.configurationid=pt.configurationid and cast(t.revisionno as int) < cast(pt.revisionno as int) AND t.' + @cn + ' is NOT NULL
ORDER BY revisionno desc)) from PIVOT_TABLE pt where pt.' + @cn + ' is NULL;'
EXEC Sp_executesql
@sql
--print @cn
END
FETCH next FROM col_names INTO @cn
END
CLOSE col_names
DEALLOCATE col_names;