2015-09-07 20 views
3

我想根據另一個表(source)中的值更新表(target)。但我正在尋找一種可以在4個主要數據庫中工作的語法 - Oracle,MS SQL Server,PostgreSQL,MySQL。在主要數據庫中工作的UPDATE語法

到目前爲止,我無法找到這樣一個統一的語法。我錯過了這樣的語法還是真的沒有這樣的語法?

甲骨文

UPDATE target t 
SET (t.col1, t.col2) = (SELECT s.col1, s.col2 
         FROM source s 
         WHERE s.key = t.key) 

MS SQL服務器/ PostgreSQL的

UPDATE target t 
SET t.col1 = s.col1, t.col2 = s.col2 
FROM source s 
WHERE t.key=s.key 

MySQL的

UPDATE target, source 
SET t.col1=s.col1, t.col2=s.col2 
WHERE s.key=t.key 

回答

3

這是低效的,但ANSI SQL標準的方式來做到這一點是:

UPDATE target 
SET col1 = (SELECT s.col1 
      FROM source s 
      WHERE s.key = target.key), 
    col2 = (SELECT s.col2 
      FROM source s 
      WHERE s.key = target.key); 

這並不意味着它會在每個RDBMS中工作(例如,我不認爲它可以在Access中工作),但它在你列出的4中有效。

我個人很重視每週每天的可移植性,所以我不會使用這種語法。我傾向於使用一個使用存儲過程的通用名稱,但每個RDBMS的語法都不相同。

UPDATE

其實,你已經使用行值構造出用於Oracle的方法也由ANSI SQL標準允許的:

UPDATE target 
SET (t.col1, t.col2) = (SELECT s.col1, s.col2 
         FROM source s 
         WHERE s.key = t.key); 

不幸的是,如上面提到的,只是因爲它是在ANSI標準中並不意味着它可以跨平臺工作。

+0

並不一定是低效 – Ben

+0

@Ben不一定,但在給定的例子,將需要從源讀取兩次,而不是一次。我會認爲這是低效的。如果更新是5列,則需要5倍的讀取次數,如果不是簡單的表查詢,子查詢更復雜,那麼更多的工作正在重複。 – GarethD

+0

我對1億行的測試(SQL Server)表明,當更新整個表時,如果有一個聚集索引,那麼每個額外的列會有20%到40%的懲罰,這些表是內存中的(希望所有時間)。這絕對有意義。所以我想這是維護多個查詢的維護頭痛與性能的重要性之間的一個折衷。 – Ben

2

ANSI更新語法(應該在你列出的DBMS工作):

update t1 
    set col1 = (
       select col1 
       from t2 
       where t1.key = t2.key 
      ), 
    set col2 = (
       select col2 
       from t2 
       where t1.key = t2.key 
      ) 
相關問題