Comment mettre à jour à partir D'un SELECT dans SQL Server?
dans SQL Server , il est possible de insert
dans un tableau en utilisant un SELECT
déclaration:
INSERT INTO Table (col1, col2, col3)
SELECT col1, col2, col3
FROM other_table
WHERE sql = 'cool'
est-il également possible de mettre à jour via un SELECT
? J'ai une table temporaire contenant les valeurs, et je voudrais mettre à jour une autre table en utilisant ces valeurs. Peut-être quelque chose comme ceci:
UPDATE Table SET col1, col2
SELECT col1, col2
FROM other_table
WHERE sql = 'cool'
WHERE Table.id = other_table.id
29 réponses
UPDATE
Table_A
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
FROM
Some_Table AS Table_A
INNER JOIN Other_Table AS Table_B
ON Table_A.id = Table_B.id
WHERE
Table_A.col3 = 'cool'
dans SQL Server 2008 (ou mieux), utilisez MERGE
MERGE INTO YourTable T
USING other_table S
ON T.id = S.id
AND S.tsql = 'cool'
WHEN MATCHED THEN
UPDATE
SET col1 = S.col1,
col2 = S.col2;
alternativement:
MERGE INTO YourTable T
USING (
SELECT id, col1, col2
FROM other_table
WHERE tsql = 'cool'
) S
ON T.id = S.id
WHEN MATCHED THEN
UPDATE
SET col1 = S.col1,
col2 = S.col2;
UPDATE table
SET Col1 = i.Col1,
Col2 = i.Col2
FROM (
SELECT ID, Col1, Col2
FROM other_table) i
WHERE
i.ID = table.ID
je modifierais L'excellente réponse de Robin à ce qui suit:
UPDATE Table
SET Table.col1 = other_table.col1,
Table.col2 = other_table.col2
FROM
Table
INNER JOIN other_table ON Table.id = other_table.id
WHERE
Table.col1 != other_table.col1
OR Table.col2 != other_table.col2
OR (
other_table.col1 IS NOT NULL
AND Table.col1 IS NULL
)
OR (
other_table.col2 IS NOT NULL
AND Table.col2 IS NULL
)
sans clause WHERE, vous affecterez même les lignes qui n'ont pas besoin d'être affectées, ce qui pourrait (peut-être) provoquer un recalcul de l'index ou des déclencheurs de feu qui ne devraient pas avoir été tirés.
One way
UPDATE t
SET t.col1 = o.col1,
t.col2 = o.col2
FROM
other_table o
JOIN
t ON t.id = o.id
WHERE
o.sql = 'cool'
une autre possibilité qui n'est pas encore mentionnée est de simplement balancer la déclaration SELECT
dans un CTE et ensuite de mettre à jour le cte.
;WITH CTE
AS (SELECT T1.Col1,
T2.Col1 AS _Col1,
T1.Col2,
T2.Col2 AS _Col2
FROM T1
JOIN T2
ON T1.id = T2.id
/*Where clause added to exclude rows that are the same in both tables
Handles NULL values correctly*/
WHERE EXISTS(SELECT T1.Col1,
T1.Col2
EXCEPT
SELECT T2.Col1,
T2.Col2))
UPDATE CTE
SET Col1 = _Col1,
Col2 = _Col2
cela a l'avantage qu'il est facile d'exécuter l'instruction SELECT
en soi en premier pour vérifier les résultats, mais il ne vous oblige à alias les colonnes comme ci-dessus si elles sont nommées le même dans les tables source et cible.
cela a également la même limitation que le propriétaire UPDATE ... FROM
syntaxe indiquée dans quatre des autres réponses. Si la table source est du côté multiple d'une jointure un-à-plusieurs, alors il n'est pas déterminé lequel des enregistrements joints possibles sera utilisé dans Update
(un problème que MERGE
évite en soulevant une erreur s'il y a une tentative de mettre à jour la même ligne plus d'une fois).
pour l'enregistrement (et d'autres recherches comme je l'étais), vous pouvez le faire en MySQL comme ceci:
UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id
utilisant l'alias:
UPDATE t
SET t.col1 = o.col1
FROM table1 AS t
INNER JOIN
table2 AS o
ON t.id = o.id
la façon simple de le faire est:
UPDATE
table_to_update,
table_info
SET
table_to_update.col1 = table_info.col1,
table_to_update.col2 = table_info.col2
WHERE
table_to_update.ID = table_info.ID
cela peut être une raison de niche pour effectuer une mise à jour (par exemple, principalement utilisé dans une procédure), ou peut être évident pour d'autres, mais il devrait également être précisé que vous pouvez effectuer une déclaration update-select sans utiliser join (dans le cas où les tables que vous mettez à jour entre n'ont pas de champ commun).
update
Table
set
Table.example = a.value
from
TableExample a
where
Table.field = *key value* -- finds the row in Table
AND a.field = *key value* -- finds the row in TableExample a
Voici une autre syntaxe utile:
UPDATE suppliers
SET supplier_name = (SELECT customers.name
FROM customers
WHERE customers.customer_id = suppliers.supplier_id)
WHERE EXISTS (SELECT customers.name
FROM customers
WHERE customers.customer_id = suppliers.supplier_id);
vérifie s'il est nul ou non en utilisant"WHERE EXIST".
j'ajoute ceci seulement pour que vous puissiez voir un moyen rapide de l'écrire pour que vous puissiez vérifier ce qui sera mis à jour avant de faire la mise à jour.
UPDATE Table
SET Table.col1 = other_table.col1,
Table.col2 = other_table.col2
--select Table.col1, other_table.col,Table.col2,other_table.col2, *
FROM Table
INNER JOIN other_table
ON Table.id = other_table.id
UPDATE from SELECT with INNER JOIN in SQL Database
comme il y a trop de réponses de ce poste, qui sont le plus fortement up-voted, j'ai pensé que je fournirais ma suggestion ici aussi. Bien que la question soit très intéressante, j'ai vu dans de nombreux sites de forum et ai fait une solution en utilisant INNER JOIN avec des captures d'écran.
au début, j'ai créé une table nommée avec schoolold et inséré peu d'enregistrements en ce qui concerne leurs noms de colonne et l'exécuter.
puis j'ai exécuté sélectionner commande pour afficher les enregistrements insérés.
puis j'ai créé une nouvelle table nommée avec schoolnew et exécuté de la même façon au-dessus des actions sur elle.
ensuite, pour afficher les enregistrements insérés, J'exécute la commande SELECT.
maintenant, ici je veux faire quelques changements dans la troisième et quatrième rangée, pour compléter cette action, j'exécute UPDATE commande avec INNER JOIN .
pour visualiser les modifications, j'exécute la commande SELECT .
vous pouvez voir comment les troisième et quatrième enregistrements de la table schoolold facilement remplacé par la table schoolnew en utilisant INNER JOIN avec l'énoncé de mise à jour.
et si vous vouliez rejoindre la table avec elle-même (ce qui n'arrivera pas trop souvent):
update t1 -- just reference table alias here
set t1.somevalue = t2.somevalue
from table1 t1 -- these rows will be the targets
inner join table1 t2 -- these rows will be used as source
on .................. -- the join clause is whatever suits you
l'exemple suivant utilise une table dérivée, une instruction SELECT après la clause FROM, pour retourner les anciennes et les nouvelles valeurs pour d'autres mises à jour:
UPDATE x
SET x.col1 = x.newCol1,
x.col2 = x.newCol2
FROM (SELECT t.col1,
t2.col1 AS newCol1,
t.col2,
t2.col2 AS newCol2
FROM [table] t
JOIN other_table t2
ON t.ID = t2.ID) x
la mise à Jour via CTE
est plus lisible que les autres réponses ici:
;WITH cte
AS (SELECT col1,col2,id
FROM other_table
WHERE sql = 'cool')
UPDATE A
SET A.col1 = B.col1,
A.col2 = B.col2
FROM table A
INNER JOIN cte B
ON A.id = B.id
si vous utilisez SQL Server, vous pouvez mettre à jour une table à partir d'une autre sans spécifier de jointure et simplement lier les deux à partir de la clause where
. Cela rend une requête SQL beaucoup plus simple:
UPDATE Table1
SET Table1.col1 = Table2.col1,
Table1.col2 = Table2.col2
FROM
Table2
WHERE
Table1.id = Table2.id
l'autre façon est d'utiliser une table dérivée:
UPDATE t
SET t.col1 = a.col1
,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id
les données de l'Échantillon
DECLARE @tbl1 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))
DECLARE @tbl2 TABLE (id INT, col1 VARCHAR(10), col2 VARCHAR(10))
INSERT @tbl1 SELECT 1, 'a', 'b' UNION SELECT 2, 'b', 'c'
INSERT @tbl2 SELECT 1, '1', '2' UNION SELECT 2, '3', '4'
UPDATE t
SET t.col1 = a.col1
,t.col2 = a.col2
FROM (
SELECT id, col1, col2 FROM @tbl2) a
INNER JOIN @tbl1 t ON t.id = a.id
SELECT * FROM @tbl1
SELECT * FROM @tbl2
UPDATE TQ
SET TQ.IsProcessed = 1, TQ.TextName = 'bla bla bla'
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0
pour être sûr que vous mettez à jour ce que vous voulez, sélectionnez d'abord
SELECT TQ.IsProcessed, 1 AS NewValue1, TQ.TextName, 'bla bla bla' AS NewValue2
FROM TableQueue TQ
INNER JOIN TableComment TC ON TC.ID = TQ.TCID
WHERE TQ.IsProcessed = 0
Utiliser:
drop table uno
drop table dos
create table uno
(
uid int,
col1 char(1),
col2 char(2)
)
create table dos
(
did int,
col1 char(1),
col2 char(2),
[sql] char(4)
)
insert into uno(uid) values (1)
insert into uno(uid) values (2)
insert into dos values (1,'a','b',null)
insert into dos values (2,'c','d','cool')
select * from uno
select * from dos
soit:
update uno set col1 = (select col1 from dos where uid = did and [sql]='cool'),
col2 = (select col2 from dos where uid = did and [sql]='cool')
ou:
update uno set col1=d.col1,col2=d.col2 from uno
inner join dos d on uid=did where [sql]='cool'
select * from uno
select * from dos
si le nom de la colonne ID est le même dans les deux tables alors il suffit de mettre le nom de la table avant la table à mettre à jour et d'utiliser un alias pour la table sélectionnée, i.e.:
update uno set col1 = (select col1 from dos d where uno.[id] = d.[id] and [sql]='cool'),
col2 = (select col2 from dos d where uno.[id] = d.[id] and [sql]='cool')
la solution ci-dessous fonctionne pour une base de données MySQL:
UPDATE table1 a , table2 b
SET a.columname = 'some value'
WHERE b.columnname IS NULL ;
il y a même une méthode plus courte, et elle pourrait surprendre pour beaucoup d'entre vous:
-- Sample data:
---------------------------------------------------------------------------
CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10));
CREATE TABLE #DESTINATION ([ID] INT, [Desc] VARCHAR(10))
INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3');
INSERT INTO #DESTINATION VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6');
---------------------------------------------------------------------------
UPDATE #DESTINATION
SET #DESTINATION.[Desc] = #SOURCE.[Desc]
FROM #SOURCE
WHERE #DESTINATION.[ID] = #SOURCE.[ID]
AND #Source.[Desc] = 'Desc_2'
dans la réponse acceptée, après le:
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
j'ajouterais:
OUTPUT deleted.*, inserted.*
ce que je fais habituellement, c'est de tout mettre dans une transaction sur rouleaux et d'utiliser le "OUTPUT"
: de cette façon, je vois tout ce qui est sur le point d'arriver. Quand je suis content de ce que je vois, je change le ROLLBACK
en COMMIT
.
j'ai habituellement besoin de documenter ce que j'ai fait, donc j'utilise l'option "results to Text"
quand j'exécute le j'enregistre le script et le résultat de la sortie. (Bien sûr, ce n'est pas pratique si j'ai changé trop de lignes)
l'autre façon de mettre à jour à partir d'une déclaration select:
UPDATE A
SET A.col = A.col,B.col1 = B.col1
FROM first_Table AS A
INNER JOIN second_Table AS B ON A.id = B.id WHERE A.col2 = 'cool'
UPDATE table AS a
INNER JOIN table2 AS b
ON a.col1 = b.col1
INNER JOIN ... AS ...
ON ... = ...
SET ...
WHERE ...
consolidant toutes les différentes approches ici.
- sélectionner mise à jour
- mise à Jour avec une expression de table commune
- Fusion
la structure de la table D'échantillon est ci-dessous et sera mise à jour de Product_BAK à la table de produit.
produit
CREATE TABLE [dbo].[Product](
[Id] [int] IDENTITY(1, 1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](100) NULL
) ON [PRIMARY]
Product_BAK
CREATE TABLE [dbo].[Product_BAK](
[Id] [int] IDENTITY(1, 1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](100) NULL
) ON [PRIMARY]
1. Sélectionnez mise à jour
update P1
set Name = P2.Name
from Product P1
inner join Product_Bak P2 on p1.id = P2.id
where p1.id = 2
2. Mise à jour avec une expression courante de la table
; With CTE as
(
select id, name from Product_Bak where id = 2
)
update P
set Name = P2.name
from product P inner join CTE P2 on P.id = P2.id
where P2.id = 2
3. Fusion
Merge into product P1
using Product_Bak P2 on P1.id = P2.id
when matched then
update set p1.[description] = p2.[description], p1.name = P2.Name;
dans la Déclaration de Fusion, nous pouvons faire inset si ne pas trouver un enregistrement correspondant dans la cible, mais exister dans le source et s'il vous plaît trouver la syntaxe:
Merge into product P1
using Product_Bak P2 on P1.id = P2.id
when matched then
update set p1.[description] = p2.[description], p1.name = P2.Name
WHEN NOT MATCHED THEN
insert (name, description)
values(p2.name, P2.description);
vous pouvez utiliser à partir de cela pour la mise à jour dans le serveur sql
UPDATE
T1
SET
T1.col1 = T2.col1,
T1.col2 = T2.col2
FROM
Table1 AS T1
INNER JOIN Table2 AS T2
ON T1.id = T2.id
WHERE
T1.col3 = 'cool'
declare @tblStudent table (id int,name varchar(300))
declare @tblMarks table (std_id int,std_name varchar(300),subject varchar(50),marks int)
insert into @tblStudent Values (1,'Abdul')
insert into @tblStudent Values(2,'Rahim')
insert into @tblMarks Values(1,'','Math',50)
insert into @tblMarks Values(1,'','History',40)
insert into @tblMarks Values(2,'','Math',30)
insert into @tblMarks Values(2,'','history',80)
select * from @tblMarks
update m
set m.std_name=s.name
from @tblMarks as m
left join @tblStudent as s on s.id=m.std_id
select * from @tblMarks