How can I do an UPDATE statement with JOIN in SQL?
我需要使用"父"表中的数据更新SQL Server 2005中的此表,请参见以下内容:
销售
1 2 3 | id (INT) udid (INT) assid (INT) |
UD
1 2 | id (INT) assid (INT) |
什么查询可以做到这一点?我想买一台
语法严格取决于您使用的SQL DBMS。下面是在ansi/iso(aka应该用于任何SQL DBMS)、mysql、SQL Server和Oracle中实现这一点的一些方法。请注意,我建议的ansi/iso方法通常比其他两种方法慢得多,但如果您使用的是MySQL、SQL Server或Oracle以外的SQL DBMS,那么这可能是唯一的方法(例如,如果您的SQL DBMS不支持
ANSI/ISO:
1 2 3 4 5 6 7 8 9 10 11 | UPDATE ud SET assid = ( SELECT sale.assid FROM sale WHERE sale.udid = ud.id ) WHERE EXISTS ( SELECT * FROM sale WHERE sale.udid = ud.id ); |
MySQL:
1 2 3 4 | UPDATE ud u INNER JOIN sale s ON u.id = s.udid SET u.assid = s.assid |
SQLServer:
1 2 3 4 5 | UPDATE u SET u.assid = s.assid FROM ud u INNER JOIN sale s ON u.id = s.udid |
PostgreSQL:
1 2 3 4 | UPDATE ud SET ud.assid = s.assid FROM sale s WHERE ud.id = s.udid; |
注意,postgres的
神谕:
1 2 3 4 5 6 7 8 | UPDATE (SELECT u.assid AS new_assid, s.assid AS old_assid FROM ud u INNER JOIN sale s ON u.id = s.udid) up SET up.new_assid = up.old_assid |
SQLite:
1 2 3 4 5 6 7 8 9 10 11 | UPDATE ud SET assid = ( SELECT sale.assid FROM sale WHERE sale.udid = ud.id ) WHERE RowID IN ( SELECT RowID FROM ud WHERE sale.udid = ud.id ); |
这应该在SQL Server中工作:
1 2 3 4 | UPDATE ud SET assid = sale.assid FROM sale WHERE sale.udid = id |
后格雷斯
1 2 3 4 5 6 7 8 9 | UPDATE table1 SET COLUMN = VALUE FROM table2, table3 WHERE table1.column_id = table2.id AND table1.column_id = table3.id AND table1.COLUMN = VALUE AND table2.COLUMN = VALUE AND table3.COLUMN = VALUE |
标准的SQL方法是
1 2 | UPDATE ud SET assid = (SELECT assid FROM sale s WHERE ud.id=s.id) |
在SQL Server上,可以使用联接
1 2 3 4 | UPDATE ud SET assid = s.assid FROM ud u JOIN sale s ON u.id=s.id |
PostgreSQL:
1 2 3 4 5 6 7 | CREATE TABLE ud (id INTEGER, assid INTEGER); CREATE TABLE sales (id INTEGER, udid INTEGER, assid INTEGER); UPDATE ud SET assid = sales.assid FROM sales WHERE sales.id = ud.id; |
使用联接多个表简化了更新查询。
1 2 3 4 5 6 7 8 | UPDATE first_table ft JOIN second_table st ON st.some_id = ft.some_id JOIN third_table tt ON tt.some_id = st.some_id ..... SET ft.some_column = some_value WHERE ft.some_column = 123456 AND st.some_column = 123456 |
注意-第一个表、第二个表、第三个表和一些列(如123456)是演示表名、列名和ID。用有效的名称替换它们。
另一个例子就是为什么SQL不能真正移植。
对于MySQL来说:
1 2 3 | UPDATE ud, sale SET ud.assid = sale.assid WHERE sale.udid = ud.id; |
有关详细信息,请阅读多表更新:http://dev.mysql.com/doc/refman/5.0/en/update.html
1 2 3 | UPDATE [LOW_PRIORITY] [IGNORE] table_references SET col_name1={expr1|DEFAULT} [, col_name2={expr2|DEFAULT}] ... [WHERE where_condition] |
我在想,最上面一篇文章中的SQL Server可以在Sybase上使用,因为它们都是T-SQL,但不幸的是,它们都不是。
对于Sybase,我发现更新需要在表本身上,而不是别名上:
1 2 3 4 5 | UPDATE ud SET u.assid = s.assid FROM ud u INNER JOIN sale s ON u.id = s.udid |
Teradata Aster提供了另一种实现目标的有趣方式:
1 2 3 4 5 | MERGE INTO ud --what trable should be updated USING sale -- from what table/relation update info should be taken ON ud.id = sale.udid --join condition WHEN MATCHED THEN UPDATE SET ud.assid = sale.assid; -- how to update |
MySQL
如果您忘记了WHERE子句并将所有条件放在ON表达式中,您将获得最佳性能。
我认为这是因为查询首先必须联接表,然后在此基础上运行WHERE子句,所以如果您可以减少联接所需的量,那么这是获取结果/执行udpate的最快方法。
例子脚本您有一个用户表。他们可以使用用户名、电子邮件或帐号登录。这些帐户可以是活动的(1)或不活动的(0)。这个表有50000行
然后你有一个用户表可以一次性禁用,因为你发现他们都做了一些不好的事情。然而,这个表有一列,用户名、电子邮件和帐号混合在一起。它还有一个"has-run"指示灯,运行后需要设置为1(真)
查询1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | UPDATE users USER INNER JOIN blacklist_users BlacklistUser ON ( USER.username = BlacklistUser.account_ref OR USER.email = BlacklistedUser.account_ref OR USER.phone_number = BlacklistUser.account_ref AND USER.is_active = 1 AND BlacklistUser.has_run = 0 ) SET USER.is_active = 0, BlacklistUser.has_run = 1; |
推理
如果必须仅在或条件上联接,则基本上需要检查每行4次,以查看它是否应该联接,并可能返回更多的行。但是,通过给它更多的条件,如果它们在连接时不满足所有条件,那么它可以"跳过"很多行。
奖金更具可读性。所有条件都在一个位置,要更新的行在一个位置
下面的语句WITH FROM关键字用于使用联接更新多行
1 2 3 | UPDATE users SET users.DivisionId=divisions.DivisionId FROM divisions JOIN users ON divisions.Name=users.Division |
在MS访问中:
1 2 3 | UPDATE ud INNER JOIN sale ON ud.id = sale.udid SET ud.assid = sale.assid; |
1 2 3 | UPDATE tblAppraisalBasicData SET tblAppraisalBasicData.ISCbo=1 FROM tblAppraisalBasicData SI INNER JOIN aaa_test RAN ON SI.EmpID = RAN.ID |
试试这个,我想这个对你有用
1 2 3 4 5 6 7 8 9 | UPDATE ud SET ud.assid = sale.assid FROM ud INNER JOIN sale ON ud.id = sale.udid WHERE sale.udid IS NOT NULL |
对于sqlite,使用rowid属性进行更新:
1 2 3 4 5 | UPDATE TABLE SET COLUMN = 'NewValue' WHERE RowID = (SELECT t1.RowID FROM TABLE t1 JOIN Table2 t2 ON t1.JoinField = t2.JoinField WHERE t2.SelectValue = 'FooMyBarPlease'); |