通过SELECT更新一个包含25列的表格?

时间:2014-09-18 06:31:06

标签: sql sql-server sql-server-2008-r2 sql-update

在SQL Server中,如果我有两个表,每个表有(25)列,如何通过SELECT更新表?

查询是:

UPDATE
    Table1
SET
    Table1.col1 = Table2.col1,
    Table1.col2 = Table2.col2,
    ...
    ...
    ...
    Table1.col25 = Table2.col25,

FROM
    Table1
INNER JOIN
    Table2
ON
    Table1.id = Table2.id

但有没有办法更新所有列,而不像上面的例子那样编写所有25列?

3 个答案:

答案 0 :(得分:6)

在SSMS中使用对象资源管理器,找到有问题的表并展开节点,以便您看到列,键,约束,触发器,索引和统计信息

将Columns文件夹拖到查询窗口窗格中。这会在一行中生成以列空格分隔的列列表。

我们将使用正则表达式将数据转换为所需的格式。

要知道的事情。

\n是换行符/回车/输入

^匹配行的开头

.一次匹配任何东西

只要可以,

*就会重复比赛

我会标记我们匹配的单词,以便我们可以使用它。这是通过大括号{}来实现的。当事情被括号括起来时,我们对序数的引用会增加。在这里,我们只使用一个,/1就足够了。

正则表达式是贪婪的,这意味着它将尽可能匹配,这不是我们想要的。不幸的是,仅SSMS 支持贪婪匹配,所以我们必须进行多次传递

(注意上面的尾随空格)

  • 理论替代:\n, T1.\1 = T2.\1

第1轮

在此步骤中,我们将强制所有列都存在于一行

重要说明:查找内容中包含一个尾随空格

  • 找到:,
  • 替换为:\n
  • 查看:Current Document
  • 使用:Regular expressions

开始

environment_id, environment_name, folder_id, description, created_by_sid, created_by_name, created_time

结果

environment_id
environment_name
folder_id
description
created_by_sid
created_by_name
created_time

我们现在已经占据了所有列,并将它们展平在左边缘。

第2轮

我们将采用所有单词并用T1 = T2

包装它们

我将使我的输出看起来与你的相似,除非我是一个领先的逗号人。

  • 找到:^{.*}
  • 替换为:, T1.\1 = T2.\1
  • 查看:Current Document
  • 使用:Regular expressions

开始     environment_id     environment_name     folder_id     描述     created_by_sid     created_by_name     CREATED_TIME

结果

,   T1.environment_id = T2.environment_id
,   T1.environment_name = T2.environment_name
,   T1.folder_id = T2.folder_id
,   T1.description = T2.description
,   T1.created_by_sid = T2.created_by_sid
,   T1.created_by_name = T2.created_by_name
,   T1.created_time = T2.created_time

现在你有一个很好的,几乎干净的列翻译列表。修剪第一个逗号并将其打入UPDATE语句

答案 1 :(得分:2)

通过一个示例来显示如何你可以完成这个 kind 的东西,我把以下的T-SQL放在一起。

USE tempdb;
CREATE TABLE T1
(
    ID INT
    , Field1 INT
    , Field2 INT
);
CREATE TABLE T2
(
    ID INT
    , Field1 INT
    , Field2 INT
);
GO
INSERT INTO T1 (ID, Field1, Field2) VALUES (1, 2, 3);
INSERT INTO T2 (ID, Field1, Field2) VALUES (1, 4, 5);

DECLARE @TableName1 SYSNAME;
DECLARE @TableName2 SYSNAME;
DECLARE @cmd NVARCHAR(max);
SET @TableName1 = 'T1';
SET @TableName2 = 'T2';
SET @cmd = '';

SELECT @cmd = @cmd + CASE WHEN @cmd = '' THEN '' ELSE ', ' END + 
    T1.TableName + '.' + T1.FieldName + ' = ' + T2.TableName + '.' + T2.FieldName
FROM (
    SELECT t1.name AS TableName, c1.name AS FieldName
    FROM sys.tables t1
        INNER JOIN sys.columns c1 ON t1.object_id = c1.object_id
    WHERE t1.name = @TableName1 AND c1.name <> 'ID'
    ) T1
INNER JOIN (
    SELECT t2.name AS TableName, c2.name AS FieldName
    FROM sys.tables t2
        INNER JOIN sys.columns c2 ON t2.object_id = c2.object_id
    WHERE t2.name = @TableName2 AND c2.name <> 'ID'
    ) T2 ON T1.FieldName = T2.FieldName

SET @cmd = 'UPDATE ' + QUOTENAME(@TableName1) + 
    ' SET ' + @cmd + 
    ' FROM ' + QUOTENAME(@TableName1) + 
    ' INNER JOIN ' + QUOTENAME(@TableName2) + 
        ' ON ' + QUOTENAME(@TableName1) + '.id = ' + QUOTENAME(@TableName2) + '.id;';

SELECT @cmd;
EXEC sp_executesql @cmd;

这要求两个表具有完全相同的结构;字段名称和数据类型必须完全匹配。我没有在输出的动态SQL中处理模式,因此您必须确保表名仅存在于单个模式中;或修改代码以处理所需的架构。

出于多种原因,我强烈建议使用此类构造 。第一;你真的要节省多少打字?第二;确保生成的UPDATE语句完全您打算充满危险。第三;动态SQL并不完全是过程缓存友好的。我可以继续谈论为什么这是一个坏主意。

答案 2 :(得分:-4)

只需遵循以下代码syntex

即可
  UPDATE Table1 SET
Table1.col1 = (SELECT col1 FROM table2 Where Table2.id=table1.id),
Table1.col2 = (SELECT col2 FROM table2 Where Table2.id=table1.id),
...
...
...
Table1.col25 = (SELECT col25 FROM table2 Where Table2.id=table1.id) FROM table1