it-swarm.com.de

Aktualisieren Sie eine Tabelle mithilfe von JOIN in SQL Server.

Ich möchte eine Spalte in einer Tabelle aktualisieren, um eine Verknüpfung zu einer anderen Tabelle herzustellen.

UPDATE table1 a 
INNER JOIN table2 b ON a.commonfield = b.[common field] 
SET a.CalculatedColumn= b.[Calculated Column]
WHERE 
    b.[common field]= a.commonfield
AND a.BatchNO = '110'

Aber es beschwert sich:

Meldung 170, Ebene 15, Status 1, Zeile 2
Zeile 2: Falsche Syntax in der Nähe von 'a'.

Was ist hier falsch?

729
Manjot

Die proprietäre UPDATE FROM-Syntax von SQL Server ist nicht ganz ausreichend. Sie sind sich auch nicht sicher, warum Sie an der Variablen CommonField teilnehmen und danach auch filtern müssen. Versuche dies:

UPDATE t1
  SET t1.CalculatedColumn = t2.[Calculated Column]
  FROM dbo.Table1 AS t1
  INNER JOIN dbo.Table2 AS t2
  ON t1.CommonField = t2.[Common Field]
  WHERE t1.BatchNo = '110';

Wenn Sie etwas wirklich Dummes tun - zum Beispiel, ständig den Wert einer Spalte auf das Aggregat einer anderen Spalte zu setzen (was gegen das Prinzip der Vermeidung redundanter Daten verstößt), können Sie einen CTE (Common Table Expression) verwenden - siehe hier und hier für weitere Details:

;WITH t2 AS
(
  SELECT [key], CalculatedColumn = SUM(some_column)
    FROM dbo.table2
    GROUP BY [key]
)
UPDATE t1
  SET t1.CalculatedColumn = t2.CalculatedColumn
  FROM dbo.table1 AS t1
  INNER JOIN t2
  ON t1.[key] = t2.[key];

Der Grund dafür ist wirklich dumm, weil Sie dieses gesamte Update jedes Mal erneut ausführen müssen, wenn sich eine Zeile in table2 ändert. Eine SUM ist etwas, das Sie zur Laufzeit immer berechnen können und dabei nie befürchten müssen, dass das Ergebnis veraltet ist.

1422
Aaron Bertrand

Versuchen Sie es so:

begin tran
    UPDATE a 
    SET a.CalculatedColumn= b.[Calculated Column]
    FROM table1 a INNER JOIN table2 b ON a.commonfield = b.[common field] 
    WHERE a.BatchNO = '110'
commit tran
40
RBarryYoung

Die Antwort von Aaron ist perfekt:

UPDATE a
  SET a.CalculatedColumn = b.[Calculated Column]
  FROM Table1 AS a
  INNER JOIN Table2 AS b
  ON a.CommonField = b.[Common Field]
  WHERE a.BatchNo = '110';

Ich möchte nur hinzufügen, warum dieses Problem in SQL Server auftritt, wenn wir versuchen, den Alias ​​einer Tabelle zu verwenden, während diese Tabelle aktualisiert wird.

update tableName t 
set t.name = 'books new' 
where t.id = 1

der Fall kann beliebig sein, wenn Sie eine einzelne Tabelle aktualisieren oder während der Verwendung von join aktualisieren.

Obige Abfrage funktioniert zwar gut in PL/SQL, jedoch nicht in SQL Server.

Die korrekte Methode zum Aktualisieren einer Tabelle während der Verwendung eines Tabellenalias in SQL Server ist:

update t 
set t.name = 'books new' 
from tableName t 
where t.id = 1

Ich hoffe, es wird allen helfen, warum der Irrtum hierher gekommen ist.

27
Ankur Bhutani
MERGE table1 T
   USING table2 S
      ON T.CommonField = S."Common Field"
         AND T.BatchNo = '110'
WHEN MATCHED THEN
   UPDATE
      SET CalculatedColumn = S."Calculated Column";
3
onedaywhen
    UPDATE mytable
         SET myfield = CASE other_field
             WHEN 1 THEN 'value'
             WHEN 2 THEN 'value'
             WHEN 3 THEN 'value'
         END
    From mytable
    Join otherTable on otherTable.id = mytable.id
    Where othertable.somecolumn = '1234'

Weitere Alternativen hier: http://www.karlrixon.co.uk/writing/update-multiple-rows-with-different-values-und-single-sql-query/

2
wut

Anscheinend kann SQL Server 2012 auch die alte Aktualisierungssyntax von Teradata verarbeiten:

UPDATE a
SET a.CalculatedColumn= b.[Calculated Column]
FROM table1 a, table2 b 
WHERE 
    b.[common field]= a.commonfield
AND a.BatchNO = '110'

Wenn ich mich recht erinnere, gab 2008R2 einen Fehler aus, als ich eine ähnliche Abfrage ausprobierte.

2
nyunyu

Ich finde es nützlich, ein UPDATE in ein SELECT umzuwandeln, um die Zeilen, die ich aktualisieren möchte, vor dem Update als Test zu erhalten. Wenn ich die genauen Zeilen auswählen kann, die ich möchte, kann ich nur die Zeilen aktualisieren, die ich aktualisieren möchte.

DECLARE @expense_report_id AS INT
SET @expense_report_id = 1027

--UPDATE expense_report_detail_distribution
--SET service_bill_id = 9

SELECT *
FROM expense_report_detail_distribution erdd
INNER JOIN expense_report_detail erd
INNER JOIN expense_report er 
    ON er.expense_report_id = erd.expense_report_id 
    ON erdd.expense_report_detail_id = erd.expense_report_detail_id
WHERE er.expense_report_id = @expense_report_id
1
CW1255

Ein anderer Ansatz wäre die Verwendung von MERGE

  ;WITH cteTable1(CalculatedColumn, CommonField)
  AS
  (
    select CalculatedColumn, CommonField from Table1 Where BatchNo = '110'
  )
  MERGE cteTable1 AS target
    USING (select "Calculated Column", "Common Field" FROM dbo.Table2) AS source ("Calculated Column", "Common Field")
    ON (target.CommonField = source."Common Field")
    WHEN MATCHED THEN 
        UPDATE SET target.CalculatedColumn = source."Calculated Column";

-Merge ist Teil des SQL-Standards

-Auch ich bin mir ziemlich sicher, dass Aktualisierungen der inneren Verknüpfungen nicht deterministisch sind. Ähnliche Frage hier, wo die Antwort darüber spricht http://ask.sqlservercentral.com/questions/19089/updating-two-tables-using- single-query.html

0
Shane Neuville

Ich hatte das gleiche Problem ... und Sie müssen keine physische Spalte hinzufügen. Cuz, jetzt müssen Sie es beibehalten ... Sie können eine generische Spalte in die Auswahlabfrage einfügen:

EX:

select tb1.col1, tb1.col2, tb1.col3 ,
( 
select 'Match' from table2 as tbl2
where tbl1.col1 = tbl2.col1 and tab1.col2 = tbl2.col2
)  
from myTable as tbl1
0
Mahmoud Sayed