MySQL有这样的东西:
INSERT INTO visits (ip, hits)
VALUES ('127.0.0.1', 1)
ON DUPLICATE KEY UPDATE hits = hits + 1;
Run Code Online (Sandbox Code Playgroud)
据我所知,SQLite中不存在此功能,我想知道的是,如果有任何方法可以实现相同的效果而无需执行两个查询.此外,如果无法做到这一点,您更喜欢什么:
我需要对SQLite数据库执行UPSERT/INSERT或UPDATE.
在许多情况下,命令INSERT OR REPLACE可能很有用.但是如果你想因为外键而使你的id保持自动增量,那么它不起作用,因为它删除了行,创建了一个新行,因此这个新行有一个新的ID.
这将是表格:
播放器 - (id上的主键,user_name唯一)
| id | user_name | age |
------------------------------
| 1982 | johnny | 23 |
| 1983 | steven | 29 |
| 1984 | pepee | 40 |
Run Code Online (Sandbox Code Playgroud) 我有下表的柜台:
CREATE TABLE cache (
key text PRIMARY KEY,
generation int
);
Run Code Online (Sandbox Code Playgroud)
我想增加其中一个计数器,或者如果相应的行还不存在则将其设置为零.有没有办法在标准SQL中没有并发问题的情况下执行此操作?该操作有时是交易的一部分,有时是分开的.
如果可能的话,SQL必须在SQLite,PostgreSQL和MySQL上不加修改地运行.
搜索产生了一些想法,这些想法要么遇到并发问题,要么特定于数据库:
尝试换INSERT行,UPDATE如果出现错误.不幸的是,INSERT中止当前事务的错误.
UPDATE行,如果没有修改行,则为INSERT新行.
MySQL有一个ON DUPLICATE KEY UPDATE条款.
编辑:感谢所有的好评.看起来保罗是对的,并没有单一,便携的方式来做到这一点.这对我来说非常令人惊讶,因为它听起来像是一个非常基本的操作.
我在表中两列col1,col2他们都是独一无二的索引(COL1是唯一的,因此是COL2).
我需要插入到这个表中,使用ON CONFLICT语法并更新其他列,但我不能同时使用两个列in conflict_target子句.
有用:
INSERT INTO table
...
ON CONFLICT ( col1 )
DO UPDATE
SET
-- update needed columns here
Run Code Online (Sandbox Code Playgroud)
但是如何为几个列执行此操作,如下所示:
...
ON CONFLICT ( col1, col2 )
DO UPDATE
SET
....
Run Code Online (Sandbox Code Playgroud) 愚蠢而简单的例子:假设我有一个表'Item',其中我保存了收到的项目的总数.
Item_Name Items_In_Stock
Run Code Online (Sandbox Code Playgroud)
项目名称是主键.当我收到数量为X的项目A时,如何实现以下目标.
如果该项目不存在,我为项目A插入一个新的,并将库存中的项目设置为X,如果存在库存中的项目为Y的记录,则库存中的项目中的新值为(X + Y)
INSERT INTO `item`
(`item_name`, items_in_stock)
VALUES( 'A', 27)
ON DUPLICATE KEY UPDATE
`new_items_count` = 27 + (SELECT items_in_stock where item_name = 'A' )
Run Code Online (Sandbox Code Playgroud)
我的问题是我的实际表中有多列.在更新部分中编写多个select语句是个好主意吗?
当然我可以在代码中完成它,但有更好的方法吗?
我正在尝试在表上执行单行插入/更新,但所有示例都是针对集合.
任何人都可以修复我的语法:
MERGE member_topic ON mt_member = 0 AND mt_topic = 110
WHEN MATCHED THEN UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test')
Run Code Online (Sandbox Code Playgroud)
每个marc_s的解析是将单行转换为子查询 - 这使我认为MERGE命令并不真正用于单行upsert.
MERGE member_topic
USING (SELECT 0 mt_member, 110 mt_topic) as source
ON member_topic.mt_member = source.mt_member AND member_topic.mt_topic = source.mt_topic
WHEN MATCHED THEN UPDATE SET mt_notes = 'test'
WHEN NOT MATCHED THEN INSERT (mt_member, mt_topic, mt_notes) VALUES (0, 110, 'test');
Run Code Online (Sandbox Code Playgroud) 我以前从未见过INSERT OR REPLACE INTO names (id, name) VALUES (1, "John")SQL中使用的语法,我想知道它为什么比它好UPDATE names SET name = "John" WHERE id = 1.是否有任何理由使用其中一个.这种语法是否特定于SQLite?
我有一个记录,我希望它存在于数据库中,如果它不存在,如果它已存在(主键存在)我希望字段更新到当前状态.这通常称为upsert.
以下不完整的代码片段演示了什么可行,但它似乎过于笨重(特别是如果有更多的列).什么是更好/最好的方式?
Base = declarative_base()
class Template(Base):
__tablename__ = 'templates'
id = Column(Integer, primary_key = True)
name = Column(String(80), unique = True, index = True)
template = Column(String(80), unique = True)
description = Column(String(200))
def __init__(self, Name, Template, Desc):
self.name = Name
self.template = Template
self.description = Desc
def UpsertDefaultTemplate():
sess = Session()
desired_default = Template("default", "AABBCC", "This is the default template")
try:
q = sess.query(Template).filter_by(name = desiredDefault.name)
existing_default = q.one()
except sqlalchemy.orm.exc.NoResultFound:
#default does not exist yet, …Run Code Online (Sandbox Code Playgroud) 在SQL Server 2005中执行原子"UPSERT"(在哪里存在UPDATE,否则为INSERT)的正确模式是什么?
我在SO上看到了很多代码(例如,请参阅检查是否存在行,否则插入),其中包含以下两部分模式:
UPDATE ...
FROM ...
WHERE <condition>
-- race condition risk here
IF @@ROWCOUNT = 0
INSERT ...
Run Code Online (Sandbox Code Playgroud)
要么
IF (SELECT COUNT(*) FROM ... WHERE <condition>) = 0
-- race condition risk here
INSERT ...
ELSE
UPDATE ...
Run Code Online (Sandbox Code Playgroud)
其中<condition>将是对自然键的评估.上述方法似乎都不能很好地处理并发问题.如果我不能拥有两个具有相同自然键的行,则似乎所有上述风险都会在竞争条件场景中插入具有相同自然键的行.
我一直在使用以下方法,但我很惊讶不要在人们的回复中看到它,所以我想知道它有什么问题:
INSERT INTO <table>
SELECT <natural keys>, <other stuff...>
FROM <table>
WHERE NOT EXISTS
-- race condition risk here?
( SELECT 1 FROM <table> WHERE <natural keys> )
UPDATE ...
WHERE <natural keys>
Run Code Online (Sandbox Code Playgroud)
请注意,此处提到的竞争条件与早期代码中的竞争条件不同.在早期的代码中,问题是幻读(在UPDATE/IF之间或在另一个会话的SELECT/INSERT之间插入行).在上面的代码中,竞争条件与DELETE有关.在(WHERE NOT EXISTS)执行之后但在INSERT执行之前,是否有可能由另一个会话删除匹配的行?目前还不清楚WHERE …
从我的代码(Java)我想确保在执行代码后数据库(DB2)中存在一行.
我的代码现在执行了一个select,如果没有返回结果,它会执行insert.我真的不喜欢这个代码,因为它在多线程环境中运行时会让我遇到并发问题.
我想要做的是将这个逻辑放在DB2而不是我的Java代码中.DB2有insert-or-update声明吗?或者我可以使用的任何类似的东西?
例如:
insertupdate into mytable values ('myid')
Run Code Online (Sandbox Code Playgroud)
另一种方法可能是始终执行insert并捕获"SQL-code -803主键已存在",但我想尽可能避免这种情况.
upsert ×10
sqlite ×4
database ×3
mysql ×3
sql ×3
postgresql ×2
sql-server ×2
atomic ×1
db2 ×1
merge ×1
performance ×1
python ×1
sqlalchemy ×1