几个月前,我从Stack Overflow的答案中学到了如何使用以下语法在MySQL中一次执行多个更新:
INSERT INTO table (id, field, field2) VALUES (1, A, X), (2, B, Y), (3, C, Z)
ON DUPLICATE KEY UPDATE field=VALUES(Col1), field2=VALUES(Col2);
Run Code Online (Sandbox Code Playgroud)
我现在切换到PostgreSQL,显然这是不正确的.它指的是所有正确的表,所以我认为这是使用不同关键字的问题,但我不确定PostgreSQL文档中的哪个被覆盖.
为了澄清,我想插入几个东西,如果它们已经存在则更新它们.
这里一个非常常见的问题是如何进行upsert,这是MySQL调用的INSERT ... ON DUPLICATE UPDATE,标准支持作为MERGE操作的一部分.
鉴于PostgreSQL不直接支持它(在第9.5页之前),你是如何做到这一点的?考虑以下:
CREATE TABLE testtable (
id integer PRIMARY KEY,
somedata text NOT NULL
);
INSERT INTO testtable (id, somedata) VALUES
(1, 'fred'),
(2, 'bob');
Run Code Online (Sandbox Code Playgroud)
现在,假设你想"UPSERT"的元组(2, 'Joe'),(3, 'Alan'),因此新表的内容是:
(1, 'fred'),
(2, 'Joe'), -- Changed value of existing tuple
(3, 'Alan') -- Added new tuple
Run Code Online (Sandbox Code Playgroud)
这是人们在讨论时所谈论的内容upsert.至关重要的是,任何方法在同一个表上存在多个事务时都必须是安全的 - 通过使用显式锁定,或以其他方式抵御由此产生的竞争条件.
关于PostgreSQL中的重复更新,在Insert上广泛讨论了这个主题?,但这是关于MySQL语法的替代品,随着时间的推移,它已经成长为一些无关的细节.我正在研究明确的答案.
这些技术对于"插入如果不存在,否则什么都不做"也很有用,即"插入...复制键忽略".
我正进入(状态
ORA-30926:无法在源表中获得稳定的行集
在以下查询中:
MERGE INTO table_1 a
USING
(SELECT a.ROWID row_id, 'Y'
FROM table_1 a ,table_2 b ,table_3 c
WHERE a.mbr = c.mbr
AND b.head = c.head
AND b.type_of_action <> '6') src
ON ( a.ROWID = src.row_id )
WHEN MATCHED THEN UPDATE SET in_correct = 'Y';
Run Code Online (Sandbox Code Playgroud)
我运行table_1它有数据,我也运行内部查询(src)也有数据.
为什么会出现此错误以及如何解决?
我们有一个非常标准的数据导入过程,我们在其中加载一个staging表,然后将MERGE其加载
到target表中.
新要求(绿色)涉及将导入数据的子集捕获到单独的queue表中,以进行完全不相关的处理.
(1)子集由选择的记录组成:target仅新添加到表中的记录.
(2)子集是一些插入列的投影,但也是至少一个仅存在于源(staging
表)中的列.
(3)该MERGE语句已OUTPUT..INTO严格使用该子句记录所$action采用的MERGE,以便我们可以
为统计目的提供PIVOT结果和COUNT插入,更新和删除的数量.我们并不喜欢像这样缓冲整个数据集的操作,而是希望动态聚合总和.不用说,我们不想在此OUTPUT表中添加更多数据.
(4)我们不想做MERGE
任何原因,甚至部分地执行第二次的匹配工作.该
target表是非常大的,我们不能索引一切,操作通常是相当昂贵的(几分钟,而不是秒).
(5)我们不考虑将任何输出从MERGE客户端传输到客户端,以便客户端可以queue通过立即将其发送回来将其路由到客户端.数据必须保留在服务器上.
(6)我们希望避免在staging和之间的临时存储中缓冲整个数据集queue.
最好的方法是什么?
(a)仅将插入的记录排入队列的要求使我们无法queue直接将表格中的表格置于OUTPUT..INTO其中MERGE,因为它不允许任何WHERE条款.我们可以使用一些
CASE技巧来标记不需要的记录,以便在queue不进行处理的情况下进行后续删除,但这看起来很疯狂.
(b)因为用于表的某些列queue没有出现在
target表中,我们不能简单地在目标表上添加插入触发器来加载queue."数据流分裂"必须尽快发生.
(c)由于我们已经在中使用了一个OUTPUT..INTO子句MERGE,我们不能添加第二个OUTPUT子句并将其 …
我有一个表中包含一些持久性数据.现在,当我查询它时,我还有一个非常复杂的CTE,它计算结果所需的值,我需要将缺少的行插入到持久表中.最后,我想选择由CTE识别的所有行组成的结果,但是如果它们已经在表中,则使用表中的数据,并且我需要有关是否刚刚插入行的信息.
简化这样的工作原理(如果您想尝试以下代码作为普通查询运行):
-- Set-up of test data, this would be the persisted table
DECLARE @target TABLE (id int NOT NULL PRIMARY KEY) ;
INSERT INTO @target (id) SELECT v.id FROM (VALUES (1), (2)) v(id);
-- START OF THE CODE IN QUESTION
-- The result table variable (will be several columns in the end)
DECLARE @result TABLE (id int NOT NULL, new bit NOT NULL) ;
WITH Source AS (
-- Imagine a fairly expensive, recursive CTE here
SELECT * FROM …Run Code Online (Sandbox Code Playgroud) 需要一点帮助,我的SQL几乎不存在......
NOT MATCHED BY SOURCE vs 之间有什么区别?NOT MATCHED BY TARGET
例如:
是否WHEN NOT MATCHED BY SOURCE意味着记录存在于目标中而不是源中?- 所以我们可以删除它们?
并且WHEN NOT MATCHED BY TARGET- 表示记录存在于源中但不存在于目标中?所以我们可以插入它们?
我有一个main数据库和report数据库,我需要从同步表main成report.
但是,当一个项目在main数据库中被删除时,我只想IsDeleted在report数据库中设置一个标志.
这样做的优雅方式是什么?
我目前正在使用MERGE语句,如下所示:
MERGE INTO report.TEST target
USING (SELECT * FROM main.TEST) source
ON (target.ID = source.ID)
WHEN MATCHED THEN
UPDATE SET (target... = source...)
WHEN NOT MATCHED THEN
INSERT (...) VALUES (source...)
;
Run Code Online (Sandbox Code Playgroud)
该WHEN NOT MATCHED语句为我提供了所有新值main,但我也希望更新所有OLD值report.
我正在使用Oracle PL/SQL.
有没有办法从.NET Entity框架4 调用T-Sql的MERGE命令?
我在数据库项目中使用MERGE语句来填充静态值集中的引用数据,如下所示:
MERGE INTO dbo.[User] AS TARGET
USING (VALUES
('me@somewhere.com', 'My Name'))
AS SOURCE(UserName, FullName)
ON SOURCE.UserName = TARGET.UserName
WHEN NOT MATCHED BY TARGET THEN
INSERT (UserId, UserName, FullName)
VALUES (NEWID(), UserName, FullName);
Run Code Online (Sandbox Code Playgroud)
当我想根据其他表中的内容填充辅助表时,会出现问题.例如,我的UserPermission表包含用户ID和角色ID,我希望我的静态值设置为('me@somewhere.com','Admin'),并且能够加入User和Permission以获得INSERTing的ID值.不知道该怎么办......
编辑:
用户表(ID,用户名)1,John Smith 2,Mark Wahlerg
角色表(ID,RoleName)1,管理员2,用户3,访客
用户角色表(用户ID,角色ID)
我希望MERGE语句的SQL调整User-Role表,以便我可以指定类似的东西:
USING(VALUES
('John Smith', 'Administrator'),
('Mark Wahlburg', 'User')
Run Code Online (Sandbox Code Playgroud)
并且它将连接以确定ID,插入不存在的组合(并且可能删除那些但不在MERGE中的组合.
解:
WITH CTE AS
(
SELECT UserId, RoleId
FROM (VALUES
('John Smith', 'Administrator'),
('Mark Wahlburg', 'User'))
AS SOURCE(UserName, RoleName)
INNER JOIN User ON SOURCE.UserName = User.UserName
INNER JOIN Role ON SOURCE.RoleName …Run Code Online (Sandbox Code Playgroud) 什么更快?
合并声明
MERGE INTO table_name
USING dual
ON (row_id = 'some_id')
WHEN MATCHED THEN
UPDATE SET col_name = 'some_val'
WHEN NOT MATCHED THEN
INSERT (row_id, col_name)
VALUES ('some_id', 'some_val')
Run Code Online (Sandbox Code Playgroud)
要么
查询select语句然后使用update或insert语句.
SELECT * FROM table_name where row_id = 'some_id'
Run Code Online (Sandbox Code Playgroud)
如果rowCount == 0
INSERT INTO table_name (row_id,col_name) VALUES ('some_id','some_val')
Run Code Online (Sandbox Code Playgroud)
其他
UPDATE table_name SET col_name='some_val' WHERE row_id='some_id'
Run Code Online (Sandbox Code Playgroud) sql-merge ×10
sql ×5
oracle ×3
sql-server ×3
t-sql ×3
postgresql ×2
upsert ×2
c# ×1
linq ×1
merge ×1
sql-update ×1