Sql 如何更新记录的所有列而不必列出每一列

Sql 如何更新记录的所有列而不必列出每一列,sql,sql-update,Sql,Sql Update,我试图找到一种方法来更新记录,而不必列出需要更新的每个列名 例如,如果我可以使用类似于以下内容的内容,那就太好了: // the parts inside braces are what I am trying to figure out UPDATE Employee SET {all columns, without listing each of them} WITH {this record with id of '111' from other table} WHERE employ

我试图找到一种方法来更新记录,而不必列出需要更新的每个列名

例如,如果我可以使用类似于以下内容的内容,那就太好了:

// the parts inside braces are what I am trying to figure out
UPDATE Employee
SET {all columns, without listing each of them} 
WITH {this record with id of '111' from other table}
WHERE employee_id = '100'
如果可以做到这一点,那么编写此类查询的最直接/有效的方法是什么?

这是不可能的

您尝试执行的操作不属于SQL规范的一部分,任何数据库供应商都不支持。请参阅、、、的SQL更新语句规范。其中每一种都只支持以下语法:

UPDATE table_reference
   SET column1 = {expression} [, column2 = {expression}] ...
[WHERE ...]

您可以通过删除表中的列,然后将该列重新添加到表中,并添加一个默认值来实现这一点。然后保存此文件需要重新生成表

使用合并如何


它使您能够运行Insert、Update和Delete。另一条建议是,如果要使用索引更新大型数据集,并且源子集比目标子集小,但两个表都非常大,请首先将更改移动到临时表。我试图合并两个表,每个表有近200万行,20条记录耗时22分钟。一旦我把delta移到临时表上,需要几秒钟的时间

这是不可能的,但是

你可以这样做:

begin tran
delete from table where CONDITION
insert into table select * from EqualDesingTabletoTable where CONDITION
commit tran

小心标识字段。

如果您使用的是Oracle,则可以使用rowtype

declare 
    var_x  TABLE_A%ROWTYPE;
Begin
    select * into var_x
    from TABLE_B where rownum = 1;

    update TABLE_A set row = var_x
    where ID = var_x.ID;
end;
/

考虑到表A和表B具有相同的模式,这里有一种使用SQL SERVER的核心方法。在尝试之前仔细考虑安全性和完整性。

它使用schema获取所有列的名称,然后组合一个大的update语句来更新除ID column之外的所有列,ID column用于连接表

这仅适用于单个列键,不适用于组合键

用法:EXEC UPDATE_ALL'source_table'、'destination_table'、'id_column'

CREATE PROCEDURE UPDATE_ALL

@SOURCE VARCHAR(100),
@DEST VARCHAR(100),
@ID VARCHAR(100)

AS

    DECLARE @SQL VARCHAR(MAX) =  

    'UPDATE D SET ' +

    -- Google 'for xml path stuff' This gets the rows from query results and 
    -- turns into comma separated list.
    STUFF((SELECT ', D.'+ COLUMN_NAME + ' = S.' + COLUMN_NAME
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = @DEST
    AND COLUMN_NAME <> @ID 
    FOR XML PATH('')),1,1,'')

    + ' FROM ' + @SOURCE + ' S JOIN ' + @DEST + ' D ON S.' +  @ID + ' = D.' + @ID

    --SELECT @SQL
    EXEC (@SQL)
这是可能的。正如npe所说,这不是一种标准做法。但如果你真的必须这样做:

1.首先是一个标量函数
CREATE FUNCTION [dte].[getCleanUpdateQuery] (@pTableName varchar(40), @pQueryFirstPart VARCHAR(200) = '', @pQueryLastPart VARCHAR(200) = '', @pIncludeCurVal BIT = 1)
RETURNS VARCHAR(8000) AS
BEGIN
DECLARE @pQuery VARCHAR(8000);
WITH cte_Temp
AS
(
    SELECT
    C.name
    FROM SYS.COLUMNS AS C
        INNER JOIN SYS.TABLES AS T ON T.object_id = C.object_id
    WHERE T.name = @pTableName
)
    SELECT @pQuery = (
    CASE @pIncludeCurVal
    WHEN 0 THEN
    (
    STUFF(
        (SELECT ', ' + name + ' = ' + @pQueryFirstPart + @pQueryLastPart FROM cte_Temp FOR XML PATH('')), 1, 2, ''
        )
    )
    ELSE
    (
    STUFF(
        (SELECT ', ' + name + ' = ' + @pQueryFirstPart + name +  @pQueryLastPart FROM cte_Temp FOR XML PATH('')), 1, 2, ''
        )
    ) END)

    RETURN 'UPDATE ' + @pTableName + ' SET ' + @pQuery
END
2.像这样使用它
DECLARE @pQuery VARCHAR(8000) = dte.getCleanUpdateQuery(<your table name>, <query part before current value>, <query part after current value>, <1 if current value is used. 0 if updating everything to a static value>);
EXEC (@pQuery)
示例2:删除不需要的文本限定符,例如。
DECLARE @pQuery VARCHAR(8000) = dte.getCleanUpdateQuery('employee', 'REPLACE(', ', ''#'', '''')', 1);
EXEC (@pQuery)

这个查询可以改进。这只是我保存的,有时我使用的。您明白了。

在Oracle PL/SQL中,您可以使用以下语法:

声明 r my_表%ROWTYPE; 开始 r、 a:=1; r、 b:=2; ... 更新我的表格 设置行=r 其中id=r.id; 终止
当然,这只是将负担从UPDATE语句转移到记录构造上,但您可能已经从某个地方获取了记录。

您如何知道要为每列分配什么值?我只是尝试用新记录id=111中的内容覆盖旧记录id=100中的所有内容。因此,例如,即使没有列出诸如first_name、last_name之类的列名,这个查询也会按顺序比较每一列,并用不同的值覆盖所有列。这有意义吗?没有切实可行的办法。您可以生成代码或执行删除-插入对。这两种方法在99%的情况下都不实用。您是否可以删除现有的行条目,而改为插入?这样做依赖于顺序列定位,通常不是最佳做法。@MichaelG-但是,为了使用插入,您仍然需要列出每一列,对吗?或者有没有一种方法可以只通过传递唯一的记录id来简单地插入记录?是的,我在这里发布问题之前花了几个小时研究解决方案,认为可能有一些只有专家知道的核心方法来完成。MERGE允许您一次完成所有操作,而不是单独进行更新、插入和删除,但是对于每个条件,您仍然必须编写所有SQL,就像它们是分开的一样。
DECLARE @pQuery VARCHAR(8000) = dte.getCleanUpdateQuery('employee', 'REPLACE(', ', ''#'', '''')', 1);
EXEC (@pQuery)