我有两个具有相同模式的表(一个是临时表)
临时表和主表都将有几行相同。
我需要更新主表,对于该主表,临时表上存在相同的条目。
什么是最好的方法?
这些表有100多个列。所以有可能不列出查询中的所有列吗?
也许您正在寻找Intersect。查询:
select *
from TableA
intersect
select *
from TableB
检索两个集合中找到的行。
关于一百列的问题,打开SQL Server Management Studio,在表中找到表,右键单击并选择“脚本表为”,然后选择“插入到”,然后选择“新建查询窗口”,以逗号分隔的列列表。
您需要使用MERGE语句。一个很好的指导是在http://technet.microsoft.com/en-us/library/bb522522.aspx
现在,只要列出列,只需使用唯一键来确定行是否公用。
您可以动态构建查询。我认为这不是一个特别优雅的解决方案,但可以完成工作:
DECLARE @TableName VARCHAR(100),
@FlagColumn VARCHAR(100)
SET @TableName = 'TestTable'
SET @FlagColumn = 'FlagColumn'
-- BUILD THE TEMPORARY TABLE
DECLARE @SQL VARCHAR(MAX)
SET @SQL = 'SELECT * INTO ##' + @TableName + ' FROM ' + @TableName
EXEC(@SQL)
-- DO STUFF
-- BUILD SQL FOR MERGE STATEMENT
SET @SQL = ''
SELECT @SQL = @SQL + ' AND main.' + COLUMN_NAME + ' = temp.' + COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @TableName
AND COLUMN_NAME != @FlagColumn
SET @SQL = 'MERGE INTO ' + @TableName + ' main USING ##' + @TableName + ' temp ON ' + STUFF(@SQL, 1, 5, '') +
' WHEN MATCHED THEN UPDATE SET ' + @FlagColumn + ' = 1;'
-- EXECUTE MERGE STATEMENT
EXEC (@SQL)
-- DROP TEMP TABLE
SET @SQL = 'DROP TABLE ##' + @TableName
EXEC (@SQL)
这比需要的动态程度更高,可以简化,因为不需要动态处理任何临时表,我刚刚这样做是因为我不知道您的表名或临时表名。
我已经通过创建下表对此进行了测试:
CREATE TABLE TestTable (FlagColumn BIT)
DECLARE @i INT = 1
DECLARE @SQL VARCHAR(MAX)
WHILE @i < 100
BEGIN
SET @SQL = 'ALTER TABLE TestTable ADD COLUMN' + CONVERT(VARCHAR, @i) + ' INT'
EXEC (@SQL)
SET @i = @i + 1
END
update MyTable set
ColumnX = ?? /* Update the columns your require to the new values */
, ColumnY = ??
from MyTable
inner join MyTempTable T on T.ColumnA = MyTable.ColumnA
and MyTable.ColumnB = T.ColumnB
/* Add as many conditions as necessary to be a match */
如果该列可以为空,则必须按照以下任一方式进行处理:
where ((MyTable.ColumnA is null and T.ColumnA is null) or MyTable.ColumnA = T.ColumnA)
或者如果您知道特定值无效,那么可以在标识列中将其设为0
where coalesce(MyTable.ColumnA,0) = coalesce(T.ColumnA,0)