В SQL Server можно вставлять строки в таблицу с помощью оператора INSERT.. SELECT
:
INSERT INTO Table (col1, col2, col3)
SELECT col1, col2, col3
FROM other_table
WHERE sql = 'cool'
Можно ли также обновить таблицу с помощью SELECT
? У меня есть временная таблица, содержащая значения, и я хотел бы обновить другую таблицу, используя эти значения. Возможно что-то вроде этого:
UPDATE Table SET col1, col2
SELECT col1, col2
FROM other_table
WHERE sql = 'cool'
WHERE Table.id = other_table.id
30 ответов
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'
SET Table.other_table_id = @NewValue
), измените оператор ON на что-то вроде ON Table.id = @IdToEdit AND other_table.id = @NewValue
SET Table_A.col1 = SUM(Table_B.col1)
или любой другой агрегат. Ответ Джамаля позволяет вам поместить агрегат в SELECT
stackoverflow.com/a/8963158/695671
В SQL Server 2008 (или новее) используйте 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;
Альтернативно:
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
связано больше ошибок (и более фундаментальных), чем с MERGE
, люди только что научились жить с ними, и они стали частью ландшафта («особенности»). Учтите, что блогов не существовало, когда UPDATE
был новичком в этом квартале.
UPDATE YourTable
SET Col1 = OtherTable.Col1,
Col2 = OtherTable.Col2
FROM (
SELECT ID, Col1, Col2
FROM other_table) AS OtherTable
WHERE
OtherTable.ID = YourTable.ID
SET Table_A.col1 = SUM(Table_B.col1)
(или любую другую агрегатную функцию). Так лучше, чем ответ Робина Дэя для этой цели.
INSERT ... SELECT
. Спасибо, что поделился!
В одну сторону
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'
Другая возможность, о которой еще не упоминалось, - это просто вставить сам оператор SELECT
в CTE, а затем обновить 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
Преимущество этого заключается в том, что оператор SELECT
легко запускается сам по себе для проверки результатов, но он требует, чтобы вы присвоили столбцам псевдонимы, как указано выше, если они имеют одинаковое имя в исходной и целевой таблицах.
Это также имеет то же ограничение, что и собственный синтаксис UPDATE ... FROM
, показанный в четырех других ответах. Если исходная таблица находится на стороне «многие» соединения «один-ко-многим», то не определено, какая из возможных совпадающих соединенных записей будет использоваться в Update
(проблема, которую MERGE
позволяет избежать, подняв ошибка, если есть попытка обновить одну и ту же строку более одного раза).
CTE
?
;WITH SomeCompexCTE AS (...), CTEAsAbove AS (SELECT T1.Col1,... FROM T1 JOIN SomeComplexCTE...) UPDATE CTEAsAbove SET Col1=_Col1, ...
Для записи (и других, ищущих, как я), вы можете сделать это в MySQL следующим образом:
UPDATE first_table, second_table
SET first_table.color = second_table.color
WHERE first_table.id = second_table.foreign_id
Использование псевдонима:
UPDATE t
SET t.col1 = o.col1
FROM table1 AS t
INNER JOIN
table2 AS o
ON t.id = o.id
Самый простой способ сделать это:
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
Это может быть нишевой причиной для выполнения обновления (например, в основном используется в процедуре) или может быть очевидным для других, но также следует указать, что вы можете выполнить оператор update-select без использования соединения (в случае таблицы, которые вы обновляете между собой, не имеют общего поля).
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
Я добавляю это только для того, чтобы вы могли быстро его записать, чтобы вы могли проверить, что будет обновлено, прежде чем выполнять обновление.
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
Если вы используете MySQL вместо SQL Server, синтаксис будет следующим:
UPDATE Table1
INNER JOIN Table2
ON Table1.id = Table2.id
SET Table1.col1 = Table2.col1,
Table1.col2 = Table2.col2
Table2.col1
? как мы это сделаем. таблица два извлекается на основе условия запроса.
И если вы хотите присоединиться к столу сам с собой (что случается не слишком часто):
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
targett1
и sourcet1
, а не (или как) комментарии.
Обновление с помощью CTE
более читабельно, чем другие ответы здесь:
;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
В следующем примере используется производная таблица, оператор SELECT после предложения FROM, чтобы вернуть старые и новые значения для дальнейших обновлений:
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
Если вы используете SQL Server, вы можете обновить одну таблицу из другой без указания соединения и просто связать две из предложения where
. Это значительно упрощает SQL-запрос:
UPDATE Table1
SET Table1.col1 = Table2.col1,
Table1.col2 = Table2.col2
FROM
Table2
WHERE
Table1.id = Table2.id
Здесь объединены все различные подходы.
- Выберите обновление
- Обновление с общим табличным выражением
- Объединить
Ниже приведен образец структуры таблицы, которая будет обновляться с Product_BAK до таблицы Product.
Товар
CREATE TABLE [dbo].[Product](
[Id] [int] IDENTITY(1, 1) NOT NULL,
[Name] [nvarchar](100) NOT NULL,
[Description] [nvarchar](100) NULL
) ON [PRIMARY]
Продукт_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. Выберите обновление.
update P1
set Name = P2.Name
from Product P1
inner join Product_Bak P2 on p1.id = P2.id
where p1.id = 2
2. Обновите общее табличное выражение
; 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. Объединить
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;
В этом операторе слияния мы можем выполнить вставку, если не нашли совпадающую запись в целевом объекте, но существуют в источнике, и найдите синтаксис:
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);
Другой способ - использовать производную таблицу:
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
Пример данных
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
Чтобы убедиться, что вы обновляете то, что хотите, выберите сначала
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
Есть даже более короткий способ , который может вас удивить:
Пример набора данных:
CREATE TABLE #SOURCE ([ID] INT, [Desc] VARCHAR(10));
CREATE TABLE #DEST ([ID] INT, [Desc] VARCHAR(10));
INSERT INTO #SOURCE VALUES(1,'Desc_1'), (2, 'Desc_2'), (3, 'Desc_3');
INSERT INTO #DEST VALUES(1,'Desc_4'), (2, 'Desc_5'), (3, 'Desc_6');
Код:
UPDATE #DEST
SET #DEST.[Desc] = #SOURCE.[Desc]
FROM #SOURCE
WHERE #DEST.[ID] = #SOURCE.[ID];
Использование:
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
ЛИБО:
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')
ИЛИ ЖЕ:
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
Если имя столбца идентификатора одинаково в обеих таблицах, просто поместите имя таблицы перед таблицей, которую нужно обновить, и используйте псевдоним для выбранной таблицы, то есть:
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')
В принятом ответе после:
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
Я бы добавил:
OUTPUT deleted.*, inserted.*
Обычно я помещаю все в откат транзакции и использую "OUTPUT"
: таким образом я вижу все, что вот-вот должно произойти. Когда мне нравится то, что я вижу, я меняю ROLLBACK
на COMMIT
.
Обычно мне нужно задокументировать то, что я сделал, поэтому я использую опцию "results to Text"
при выполнении запроса с откатом и сохраняю как сценарий, так и результат ВЫХОДА. (Конечно, это непрактично, если я изменил слишком много строк)
UPDATE table AS a
INNER JOIN table2 AS b
ON a.col1 = b.col1
INNER JOIN ... AS ...
ON ... = ...
SET ...
WHERE ...
Приведенное ниже решение работает для базы данных MySQL:
UPDATE table1 a , table2 b
SET a.columname = 'some value'
WHERE b.columnname IS NULL ;
Другой способ обновления из оператора выбора:
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'
Я бы изменил отличный ответ Робина < / a> к следующему:
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
)
Без предложения WHERE вы затронете даже строки, которые не должны быть затронуты, что может (возможно) вызвать перерасчет индекса или сработать триггеры, которые действительно не должны были запускаться.
ОБНОВЛЕНИЕ из SELECT с INNER JOIN в базе данных SQL
Поскольку на этот пост слишком много ответов, которые получили наибольшее количество голосов, я подумал, что внесу свое предложение и здесь. Хотя вопрос очень интересный, я видел на многих форумах и нашел решение, используя INNER JOIN со скриншотами.
Сначала я создал таблицу с именем schoolold , вставил несколько записей в соответствии с именами столбцов и выполнил ее.
Затем я выполнил команду SELECT , чтобы просмотреть вставленные записи.
Затем я создал новую таблицу с именем schoolnew и аналогичным образом выполнил над ней действия.
Затем, чтобы просмотреть вставленные в него записи, я выполняю команду SELECT.
Теперь, здесь я хочу внести некоторые изменения в третью и четвертую строки, чтобы завершить это действие, я выполняю команду UPDATE с помощью INNER JOIN .
Чтобы просмотреть изменения, я выполняю команду ВЫБРАТЬ .
Вы можете увидеть, как третья и четвертая записи таблицы schoolold легко заменяются таблицей schoolnew с помощью INNER JOIN с оператором UPDATE.
Вариант 1. Использование внутреннего соединения:
UPDATE
A
SET
A.col1 = B.col1,
A.col2 = B.col2
FROM
Some_Table AS A
INNER JOIN Other_Table AS B
ON A.id = B.id
WHERE
A.col3 = 'cool'
Вариант 2: сопутствующий подзапрос
UPDATE table
SET Col1 = B.Col1,
Col2 = B.Col2
FROM (
SELECT ID, Col1, Col2
FROM other_table) B
WHERE
B.ID = table.ID
UPDATE table1
SET column1 = (SELECT expression1
FROM table2
WHERE conditions)
[WHERE conditions];
Синтаксис оператора UPDATE при обновлении одной таблицы данными из другой таблицы в SQL Server
Важно отметить, что, как и другие, MySQL или MariaDB используют другой синтаксис. Также он поддерживает очень удобный синтаксис USING (в отличие от T / SQL). Также INNER JOIN является синонимом JOIN. Поэтому запрос в исходном вопросе лучше всего реализовать в MySQL следующим образом:
UPDATE
Some_Table AS Table_A
JOIN
Other_Table AS Table_B USING(id)
SET
Table_A.col1 = Table_B.col1,
Table_A.col2 = Table_B.col2
WHERE
Table_A.col3 = 'cool'
Я не видел решения заданного вопроса в других ответах, поэтому мои два цента. (проверено на PHP 7.4.0 MariaDB 10.4.10)
Вот еще один полезный синтаксис:
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);
Он проверяет, является ли он нулевым, используя "WHERE EXIST".
Похожие вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.