ChatGPT解决这个技术问题 Extra ChatGPT

如何在 SQL Server 2005 的一个语句中更新两个表?

我想一口气更新两个表。我如何在 SQL Server 2005 中做到这一点?

UPDATE 
  Table1, 
  Table2
SET 
  Table1.LastName='DR. XXXXXX', 
  Table2.WAprrs='start,stop'
FROM 
  Table1 T1, 
  Table2 T2
WHERE 
  T1.id = T2.id
AND 
  T1.id = '010008'
如果您解释原因会有所帮助。
恐怕,SQL Server 2005 不支持在一个查询中更新多个表。

R
Ramil Aliyev

您不能在一个语句中更新多个表,但是,您可以使用事务来确保以原子方式处理两个 UPDATE 语句。您还可以对它们进行批处理以避免往返。

BEGIN TRANSACTION;

UPDATE Table1
SET Table1.LastName = 'DR. XXXXXX' 
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

UPDATE Table2
SET Table2.WAprrs = 'start,stop'
FROM Table1 T1, Table2 T2
WHERE T1.id = T2.id
and T1.id = '011008';

COMMIT;

实际上,我正在从另一个 temptable 更新这两个表的记录。 temptable 具有指向 table1 但没有指向 table2 的链接。如何更新 Table2 的相同记录?我将如何链接它?
@unknown:根据您的评论,如果您的更新查询需要第三个表中的键,则在更新 Table2 时需要同时加入 Table1 和 Table2。无论如何,您仍然需要进行两次单独的更新。
可能不相关:这在 MYSQL 上不起作用,因为 mysql 的更新语法不同。你必须去 UPDATE Table1 , Table2 SET Table1.LastName = 'DR. XXXXXX' 其中 T1.id = T2.id
我们是否需要维护它们之间的主键和外键关系
您还应该将更新语句放在 try/catch 块中,以避免出现错误时部分更新。看到这个问题:stackoverflow.com/questions/1749719/…
R
Rhaokiel

您不能同时更新两个表,但可以使用 OUTPUT INTO 将更新链接到插入,并且可以将此输出用作第二次更新的连接:

DECLARE @ids TABLE (id int);
BEGIN TRANSACTION

UPDATE Table1 
SET Table1.LastName = 'DR. XXXXXX'  
OUTPUT INSERTED.id INTO @ids
WHERE Table1.field = '010008';

UPDATE Table2 
SET Table2.WAprrs = 'start,stop' 
FROM Table2 
JOIN @ids i on i.id = Table2.id;

COMMIT;

我将您的示例 WHERE 条件更改为 id 以外的其他字段。如果它是 id,您不需要这个花哨的 OUTPUT,您可以只 UPDATE 为同一个 id='010008' 的第二个表。


这是最好的答案,应该被选为原始问题的真实答案。谢谢你。它对我有用。
T1.field 应该是 Table1.field 吗?
如果您想知道“OUTPUT INSERTED.id”中的 INSERTED 是什么意思,请看这里:“INSERTED - 是列前缀,指定插入或更新操作添加的值。以 INSERTED 为前缀的列反映了 UPDATE、INSERT 之后的值, 或 MERGE 语句已完成但在触发器执行之前。”链接:docs.microsoft.com/en-us/sql/t-sql/queries/…
C
Charles Bretana

对不起,afaik,你不能那样做。要更新两个不同表中的属性,您需要执行两个单独的语句。但它们可以是成批的(一组 SQL 一次往返发送到服务器)


C
Community

对此的简短回答是否定的。虽然您可以在更新语句的 from 子句中输入多个表,但您只能在 update 关键字之后指定一个表。即使您确实编写了一个“可更新”视图(它只是一个遵循某些限制的视图),这样的更新也会失败。以下是 MSDN 文档中的相关剪辑(重点是我的)。

UPDATE (Transact-SQL)

table_or_view_name 引用的视图必须是可更新的,并且在视图的 FROM 子句中只引用一个基表。有关可更新视图的详细信息,请参阅 CREATE VIEW (Transact-SQL)。

CREATE VIEW (Transact-SQL)

只要满足以下条件,您就可以通过视图修改基础基表的数据: 任何修改,包括 UPDATE、INSERT 和 DELETE 语句,都必须仅引用一个基表中的列。视图中被修改的列必须直接引用表列中的基础数据。列不能以任何其他方式派生,例如通过以下方式: 聚合函数:AVG、COUNT、SUM、MIN、MAX、GROUPING、STDEV、STDEVP、VAR 和 VARP。一个计算。无法从使用其他列的表达式计算该列。使用集合运算符 UNION、UNION ALL、CROSSJOIN、EXCEPT 和 INTERSECT 形成的列相当于计算并且也不可更新。正在修改的列不受 GROUP BY、HAVING 或 DISTINCT 子句的影响。 TOP 不与 WITH CHECK OPTION 子句一起在视图的 select_statement 中的任何地方使用。

不过,老实说,您应该考虑按照 LBushkin 的示例在事务中使用两个不同的 SQL 语句。

更新:我最初断言您可以在可更新视图中更新多个表是错误的。在 SQL Server 2005 & 2012 上,它会产生以下错误。我已经更正了我的答案以反映这一点。

消息 4405,级别 16,状态 1,第 1 行视图或函数“updatable_view”不可更新,因为修改会影响多个基表。


虽然无法更新会影响多个表的 View 对象,但您可以创建 INSTEAD OF triggers,将原始语句分成单独的语句(每个语句影响一个表):INSTEAD OF Specifies that the DML trigger is executed instead of the triggering SQL statement, therefore, overriding the actions of the triggering statements. INSTEAD OF cannot be specified for DDL or logon triggers.
s
slavoo

这适用于 MySQL,实际上只是一个隐式事务,但它应该是这样的:

UPDATE Table1 t1, Table2 t2 SET 
t2.field = t2.field+2,
t1.field = t1.field+2

WHERE t1.id = t2.foreign_id and t2.id = '123414'

如果您正在对需要多条语句的多个表进行更新……如果您更新一个,然后根据其他条件更新另一个……您应该使用事务。


此分析器仍然与其他用户相关。
@Kyselejsyreček 应该不惜一切代价避免这个答案。 MySQL 有足够多的怪癖和异味,其中大部分实际上不受支持,但保留下来以避免破坏依赖于这些怪癖的代码。升级很容易破坏它们或导致意外的行为和性能问题
M
Mick

您应该在事务中放置两个更新语句


S
Sandip - Frontend Developer

您可以为一个表编写更新语句,然后在第一个表更新时触发一个触发器,它会更新第二个表


R
Ricardo Roa

从我的角度来看,您可以这样做,它对 SQL SERVER 中的两个表进行一对一的更新:

 BEGIN TRANSACTION

      DECLARE @CNSREQ VARCHAR(30)
      DECLARE @ID INT
      DECLARE @CNSRQDT VARCHAR(30)
      DECLARE @ID2 INT

      DECLARE @IDCNSREQ INT
      DECLARE @FINALCNSREQ VARCHAR(30)
      DECLARE @FINALCNSRQDT VARCHAR(30)
      DECLARE @IDCNSRQDT INT


      SET @CNSREQ=(SELECT MIN(REQUISICIONESDT.CNSREQ) FROM REQUISICIONESDT
          INNER JOIN 
              REQUISICIONES
                ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
           AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID)

      SELECT REQUISICIONES.CNSREQ, REQUISICIONES.ID, REQUISICIONES.CNSRQDT FROM REQUISICIONES
       INNER JOIN 
          REQUISICIONESDT
              ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
               AND REQUISICIONES.CNSREQ = REQUISICIONESDT.CNSREQ AND REQUISICIONESDT.IDREQ = REQUISICIONES.ID
        WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
    AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONESDT SET  REQUISICIONESDT.CNSREQ=NULL, REQUISICIONESDT.IDREQ=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
             ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
      AND REQUISICIONES.CNSREQ = @CNSREQ

        UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT=NULL, REQUISICIONES.IDRQDT=NULL
          FROM REQUISICIONES INNER JOIN REQUISICIONESDT
          ON REQUISICIONESDT.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
       WHERE REQUISICIONES.CNSRQDT = REQUISICIONES.CNSRQDT AND REQUISICIONES.IDRQDT = REQUISICIONESDT.ID
     AND REQUISICIONES.CNSREQ = @CNSREQ

       SET @ID2=(SELECT MIN(REQUISICIONESDT.ID) FROM REQUISICIONESDT
        WHERE ISNULL(REQUISICIONESDT.IDREQ,0)<>0)
     DELETE FROM REQUISICIONESDT WHERE REQUISICIONESDT.ID=@ID2


      SET @IDCNSREQ=(SELECT MIN (REQUISICIONES.ID)FROM REQUISICIONES
          INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

        SET @FINALCNSREQ=(SELECT MIN (REQUISICIONES.CNSREQ)FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
        REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

         SET @FINALCNSRQDT=(SELECT MIN(REQUISICIONESDT.CNSRQDT) FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
          REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
           WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

          SET @IDCNSRQDT=(SELECT MIN (REQUISICIONESDT.ID)FROM REQUISICIONES
           INNER JOIN REQUISICIONESDT ON
         REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD  
         WHERE REQUISICIONES.CNSRQDT IS NULL AND REQUISICIONES.IDRQDT IS NULL)

           UPDATE REQUISICIONES SET REQUISICIONES.CNSRQDT = @FINALCNSRQDT, REQUISICIONES.IDRQDT=@IDCNSRQDT FROM REQUISICIONES
            INNER JOIN REQUISICIONESDT ON
             REQUISICIONESDT.CEDULA = REQUISICIONES.CEDULA AND REQUISICIONES.FECHA_SOLICITUD = REQUISICIONESDT.FECHA_SOLICITUD
            WHERE REQUISICIONESDT.CNSRQDT = @FINALCNSRQDT AND REQUISICIONESDT.ID = @IDCNSRQDT 


ROLLBACK TRANSACTION

m
marc_s

对于基于 Table2 特定列的一般更新 table1 特定列,此查询完美运行:

UPDATE table 1  
SET Col 2 = t2.Col2,  
    Col 3 = t2.Col3  
FROM table1 t1  
INNER JOIN table 2 t2 ON t1.Col1 = t2.col1 

M
Mohit Gupta

就像下面显示的这个查询一样简单。

UPDATE 
  Table1 T1 join Table2 T2 on T1.id = T2.id
SET 
  T1.LastName='DR. XXXXXX', 
  T2.WAprrs='start,stop'
WHERE 
  T1.id = '010008'