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?
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.
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
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.
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";
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/
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.
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
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
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