我有一个有帐号和卡号的数据库。我将这些匹配到一个文件,以将任何卡号更新为帐号,这样我只使用帐号。

我创建了一个将表链接到帐户/卡数据库的视图,以返回table ID和相关的帐号,现在我需要更新那些ID与account number匹配的记录。

这是Sales_Import表,其中的帐号字段需要更新:

LeadID AccountNumber
147 5807811235
150 5807811326
185 7006100100007267039

这是RetrieveAccountNumber表,我需要从这里更新:

LeadID AccountNumber
147 7006100100007266957
150 7006100100007267039

我尝试了下面的方法,但到目前为止运气都不佳:

UPDATE [Sales_Lead].[dbo].[Sales_Import] 
SET    [AccountNumber] = (SELECT RetrieveAccountNumber.AccountNumber 
                          FROM   RetrieveAccountNumber 
                          WHERE  [Sales_Lead].[dbo].[Sales_Import]. LeadID = 
                                                RetrieveAccountNumber.LeadID) 

它将卡号更新为帐号,但是帐号被NULL替换


我相信一个带JOIN的UPDATE FROM会有帮助:

MS SQL

UPDATE
    Sales_Import
SET
    Sales_Import.AccountNumber = RAN.AccountNumber
FROM
    Sales_Import SI
INNER JOIN
    RetrieveAccountNumber RAN
ON 
    SI.LeadID = RAN.LeadID;

MySQL和MariaDB

UPDATE
    Sales_Import SI,
    RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID;

似乎你正在使用MSSQL,然后,如果我没记错,它是这样做的:

UPDATE [Sales_Lead].[dbo].[Sales_Import] SET [AccountNumber] = 
RetrieveAccountNumber.AccountNumber 
FROM RetrieveAccountNumber 
WHERE [Sales_Lead].[dbo].[Sales_Import].LeadID = RetrieveAccountNumber.LeadID

谢谢你的回复。但我找到了一个解决办法。

UPDATE Sales_Import 
SET    AccountNumber = (SELECT RetrieveAccountNumber.AccountNumber 
                          FROM   RetrieveAccountNumber 
                          WHERE  Sales_Import.leadid =RetrieveAccountNumber.LeadID) 
WHERE Sales_Import.leadid = (SELECT  RetrieveAccountNumber.LeadID 
                             FROM   RetrieveAccountNumber 
                             WHERE  Sales_Import.leadid = RetrieveAccountNumber.LeadID)  

我对foo也有同样的问题。对于在bar中没有匹配键的foo行,New被设置为null。我在Oracle做了类似的事情:

update foo
set    foo.new = (select bar.new
                  from bar 
                  where foo.key = bar.key)
where exists (select 1
              from bar
              where foo.key = bar.key)

将内容从一个表复制到另一个表的简单方法如下:

UPDATE table2 
SET table2.col1 = table1.col1, 
table2.col2 = table1.col2,
...
FROM table1, table2 
WHERE table1.memberid = table2.memberid

还可以添加条件以复制特定的数据。


对于SQL Server 2008 +使用MERGE而不是专有的更新…FROM语法有一些吸引力。

它不仅是标准SQL,因此更易于移植,而且在源端有多个连接行的情况下(因此在更新中可能使用多个不同的值)也会引发错误,而不是最终结果不确定。

MERGE INTO Sales_Import
   USING RetrieveAccountNumber
      ON Sales_Import.LeadID = RetrieveAccountNumber.LeadID
WHEN MATCHED THEN
   UPDATE 
      SET AccountNumber = RetrieveAccountNumber.AccountNumber;

然而,不幸的是,选择使用哪一种可能并不完全取决于首选的风格。SQL Server中MERGE的实现一直受到各种错误的困扰。Aaron Bertrand在这里整理了一份报告的清单。


对于MySql工作良好:

UPDATE
    Sales_Import SI,RetrieveAccountNumber RAN
SET
    SI.AccountNumber = RAN.AccountNumber
WHERE
    SI.LeadID = RAN.LeadID

我认为这是一个简单的例子,可能有人会更容易理解,

        DECLARE @TB1 TABLE
        (
            No Int
            ,Name NVarchar(50)
        )

        DECLARE @TB2 TABLE
        (
            No Int
            ,Name NVarchar(50)
        )

        INSERT INTO @TB1 VALUES(1,'asdf');
        INSERT INTO @TB1 VALUES(2,'awerq');


        INSERT INTO @TB2 VALUES(1,';oiup');
        INSERT INTO @TB2 VALUES(2,'lkjhj');

        SELECT * FROM @TB1

        UPDATE @TB1 SET Name =S.Name
        FROM @TB1 T
        INNER JOIN @TB2 S
                ON S.No = T.No

        SELECT * FROM @TB1

在同一个表内更新:

  DECLARE @TB1 TABLE
    (
        No Int
        ,Name NVarchar(50)
        ,linkNo int
    )

    DECLARE @TB2 TABLE
    (
        No Int
        ,Name NVarchar(50)
        ,linkNo int
    )

    INSERT INTO @TB1 VALUES(1,'changed person data',  0);
    INSERT INTO @TB1 VALUES(2,'old linked data of person', 1);

INSERT INTO @TB2 SELECT * FROM @TB1 WHERE linkNo = 0


SELECT * FROM @TB1
SELECT * FROM @TB2


    UPDATE @TB1 
        SET Name = T2.Name
    FROM        @TB1 T1
    INNER JOIN  @TB2 T2 ON T2.No = T1.linkNo

    SELECT * FROM @TB1

PostgreSQL的:

UPDATE Sales_Import SI
SET AccountNumber = RAN.AccountNumber
FROM RetrieveAccountNumber RAN
WHERE RAN.LeadID = SI.LeadID; 

这将允许您根据未在另一个表中找到的列值更新表。

UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
        SELECT * 
        FROM (
                SELECT table1.id
                FROM  table1 
                LEFT JOIN table2 ON ( table2.column = table1.column ) 
                WHERE table1.column = 'some_expected_val'
                AND table12.column IS NULL
        ) AS Xalias
)

这将根据在两个表中找到的列值更新一个表。

UPDATE table1 SET table1.column = 'some_new_val' WHERE table1.id IN (
        SELECT * 
        FROM (
                SELECT table1.id
                FROM  table1 
                JOIN table2 ON ( table2.column = table1.column ) 
                WHERE table1.column = 'some_expected_val'
        ) AS Xalias
)

它与postgresql一起工作

UPDATE application
SET omts_received_date = (
    SELECT
        date_created
    FROM
        application_history
    WHERE
        application.id = application_history.application_id
    AND application_history.application_status_id = 8
);

下面的SQL有人建议,不工作在SQL Server。这个语法让我想起了我以前的学校类:

UPDATE table2 
SET table2.col1 = table1.col1, 
table2.col2 = table1.col2,
...
FROM table1, table2 
WHERE table1.memberid = table2.memberid

不建议使用NOT IN或NOT EXISTS的所有其他查询。显示null是因为OP将整个数据集与较小的子集进行比较,当然会有匹配问题。这必须通过使用正确的JOIN编写正确的SQL来解决,而不是使用NOT IN来逃避问题。在这种情况下,使用NOT IN或NOT EXISTS可能会遇到其他问题。

我投票给最上面的,这是一种传统的方法,通过加入SQL Server来根据另一个表更新一个表。就像我说的,你不能在SQL Server的同一个UPDATE语句中使用两个表,除非你先连接它们。


为未来的开发人员提供的一般答案。

SQL Server

UPDATE 
     t1
SET 
     t1.column = t2.column
FROM 
     Table1 t1 
     INNER JOIN Table2 t2 
     ON t1.id = t2.id;

Oracle(和SQL Server)

UPDATE 
     t1
SET 
     t1.colmun = t2.column 
FROM 
     Table1 t1, 
     Table2 t2 
WHERE 
     t1.ID = t2.ID;

MySQL

UPDATE 
     Table1 t1, 
     Table2 t2
SET 
     t1.column = t2.column 
WHERE
     t1.ID = t2.ID;

试试这个:

UPDATE
    Table_A
SET
    Table_A.AccountNumber = Table_B.AccountNumber ,
FROM
    dbo.Sales_Import AS Table_A
    INNER JOIN dbo.RetrieveAccountNumber AS Table_B
        ON Table_A.LeadID = Table_B.LeadID 
WHERE
    Table_A.LeadID = Table_B.LeadID

我想再补充一点。

不要用相同的值更新一个值,这会产生额外的日志记录和不必要的开销。 参见下面的例子-尽管链接了3条记录,但它只会在2条记录上执行更新。

DROP TABLE #TMP1
DROP TABLE #TMP2
CREATE TABLE #TMP1(LeadID Int,AccountNumber NVarchar(50))
CREATE TABLE #TMP2(LeadID Int,AccountNumber NVarchar(50))

INSERT INTO #TMP1 VALUES
(147,'5807811235')
,(150,'5807811326')
,(185,'7006100100007267039');

INSERT INTO #TMP2 VALUES
(147,'7006100100007266957')
,(150,'7006100100007267039')
,(185,'7006100100007267039');

UPDATE A
SET A.AccountNumber = B.AccountNumber
FROM
    #TMP1 A 
        INNER JOIN #TMP2 B
        ON
        A.LeadID = B.LeadID
WHERE
    A.AccountNumber <> B.AccountNumber  --DON'T OVERWRITE A VALUE WITH THE SAME VALUE

SELECT * FROM #TMP1

使用下面的查询块根据ID更新Table1和Table2:

UPDATE Sales_Import, RetrieveAccountNumber 
SET Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber 
where Sales_Import.LeadID = RetrieveAccountNumber.LeadID;

这是解决这个问题最简单的方法。


如果以上答案不适合你,试试这个

Update Sales_Import A left join RetrieveAccountNumber B on A.LeadID = B.LeadID
Set A.AccountNumber = B.AccountNumber
where A.LeadID = B.LeadID 

下面是在SQL Server中对我有效的方法:

UPDATE [AspNetUsers] SET

[AspNetUsers].[OrganizationId] = [UserProfile].[OrganizationId],
[AspNetUsers].[Name] = [UserProfile].[Name]

FROM [AspNetUsers], [UserProfile]
WHERE [AspNetUsers].[Id] = [UserProfile].[Id];

Oracle 11 g

merge into Sales_Import
using RetrieveAccountNumber
on (Sales_Import.LeadId = RetrieveAccountNumber.LeadId)
when matched then update set Sales_Import.AccountNumber = RetrieveAccountNumber.AccountNumber;

MS Sql

UPDATE  c4 SET Price=cp.Price*p.FactorRate FROM TableNamea_A c4
inner join TableNamea_B p on c4.Calcid=p.calcid 
inner join TableNamea_A cp on c4.Calcid=cp.calcid 
WHERE c4..Name='MyName';

Oracle 11 g

        MERGE INTO  TableNamea_A u 
        using
        (
                SELECT c4.TableName_A_ID,(cp.Price*p.FactorRate) as CalcTot 
                FROM TableNamea_A c4
                inner join TableNamea_B p on c4.Calcid=p.calcid 
                inner join TableNamea_A cp on c4.Calcid=cp.calcid 
                WHERE p.Name='MyName' 
        )  rt
        on (u.TableNamea_A_ID=rt.TableNamea_B_ID)
        WHEN MATCHED THEN
        Update set Price=CalcTot  ;

以防表在不同的数据库中。(该)

update database1..Ciudad
set CiudadDistrito=c2.CiudadDistrito

FROM database1..Ciudad c1
 inner join 
  database2..Ciudad c2 on c2.CiudadID=c1.CiudadID

根据匹配的id从一个表更新到另一个表

UPDATE 
     TABLE1 t1, 
     TABLE2 t2
SET 
     t1.column_name = t2.column_name 
WHERE
     t1.id = t2.id;

MYSQL(这是我最喜欢的恢复所有特定列reasonId值的方法,基于主键id等价)

UPDATE `site` AS destination  
INNER JOIN `site_copy` AS backupOnTuesday 
      ON backupOnTuesday.`id` = destination.`id`
SET destdestination.`reasonId` = backupOnTuesday.`reasonId`

这是Mysql和Maria DB最简单和最好的

UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id

注意:如果您遇到以下错误基于您的Mysql/Maria DB版本“错误代码:1175。您正在使用安全更新模式,并且您试图更新一个没有使用KEY列的WHERE的表。要禁用安全模式,请切换首选项中的选项。

然后像这样运行代码

SET SQL_SAFE_UPDATES=0;
UPDATE table2, table1 SET table2.by_department = table1.department WHERE table1.id = table2.by_id

甲骨文

use

UPDATE suppliers
SET supplier_name = (SELECT customers.customer_name
                     FROM customers
                     WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT customers.customer_name
              FROM customers
              WHERE customers.customer_id = suppliers.supplier_id);


对于Oracle SQL,请尝试使用别名

UPDATE Sales_Lead.dbo.Sales_Import SI 
SET SI.AccountNumber = (SELECT RAN.AccountNumber FROM RetrieveAccountNumber RAN WHERE RAN.LeadID = SI.LeadID);

更新表1 DPM set col1 = dpu。Col1 from table2 dpu其中dpm。Parameter_master_id = dpu.parameter_master_id;


总结其他答案,关于如何仅在“匹配存在”时使用来自另一个表的数据更新目标表,有4种变体

查询和子查询:

update si
set    si.AccountNumber = (
    select ran.AccountNumber 
    from   RetrieveAccountNumber ran
    where  si.LeadID = ran.LeadID
)
from Sales_Import si
where exists (select * from RetrieveAccountNumber ran where ran.LeadID = si.LeadID)

内连接:

update si
set si.AccountNumber = ran.AccountNumber
from Sales_Import si inner join RetrieveAccountNumber ran on si.LeadID = ran.LeadID

交叉连接:

update si
set si.AccountNumber = ran.AccountNumber
from Sales_Import si, RetrieveAccountNumber ran
where si.LeadID = ran.LeadID

走:

merge into Sales_Import si
using RetrieveAccountNumber ran on si.LeadID = ran.LeadID 
when matched then update set si.accountnumber = ran.accountnumber;

所有的变体都是更少的琐碎和可以理解的,我个人更喜欢“内部连接”选项。但其中任何一种都可以使用,开发者必须根据自己的需求选择“更好的选项”

从性能的角度来看,使用join的变体更可取: