Mysql 在表复制操作中更新现有行和插入不存在行的最有效方法是什么?

Mysql 在表复制操作中更新现有行和插入不存在行的最有效方法是什么?,mysql,sql,Mysql,Sql,我有两张桌子: stock: pid name qty --- ---- --- 1 aaaa 2 2 bbbb 3 1 aaaa 5 3 cccc 1 2 bbbb 2 stock_total: pid name total_qty --- ---- --------- 我可以使用此查询从stock表中插入行,将总数量添加到stock\u total INSERT INTO stock_total (pid, name, total_qty) S

我有两张桌子:

stock:

pid name qty
--- ---- ---
1   aaaa   2
2   bbbb   3
1   aaaa   5
3   cccc   1
2   bbbb   2

stock_total:

pid name total_qty
--- ---- ---------
我可以使用此查询从
stock
表中插入行,将总数量添加到
stock\u total

INSERT INTO stock_total (pid, name, total_qty)
SELECT pid, name, SUM(qty) 
FROM stock
GROUP BY pid, name
问题是,我将通过cron作业运行上面的SQL。因此,在下一次执行时,SQL应该更新现有产品并插入不存在的产品

如果我循环选择结果,检查每一行是否存在于
stock\u total
中,并进行插入或更新,那么效率将非常低


有没有更简单的方法来实现这一点?也许可以通过修改上面的SQL。谢谢。

使用
重复密钥更新

INSERT INTO TABLENAME(col1, col2)
VALUES (@value, ‘yyy’)
ON DUPLICATE KEY UPDATE col1 = @value
这是更新的一部分:

UPDATE stock_total
SET total_qty = SUM(s.qty)
FROM stock_total st
INNER JOIN stock s
ON st.pid = s.pid
AND st.name = s.name
WHERE s.pid = st.pid
GROUP BY s.pid
这是插入的内容:

INSERT INTO stock_total
SELECT s.pid, s.name, SUM(s.qty)
FROM stock s
WHERE s.pid NOT IN (SELECT pid FROM stock_total)
GROUP BY s.pid, s.name

应该可以,试一试。

为什么不从作业中调用存储过程


在块中的SP中捕获
重复键
异常和
更新
。如果没有抛出异常,它将插入您正在搜索的内容。使用方法如下—

merge into stock_total s " +
                        "using (select ? pid, ? name, ? total_qty from dual) d " +
                        "on (s.pid = d.pid and s.name = d.name and s.total_qty = d.total_qty) " +
                        "when matched then " +
                        "update set s.pid= d.pid, s.name = d.name, s.total_qty = d.total_qty" +
                        "when not matched then " +
                        "insert (pid, name, total_qty) " + 
                        "values(d.pid, d.name, d.total_qty)" ;
编辑(对于mySQL):


在谷歌搜索和试验了一些答案之后,我想出了这个解决方案。事实证明,MySQL支持在重复密钥更新时将
替换为…
。所以我的问题是这样的:

REPLACE INTO stock_total
SELECT pid, name, SUM(qty)
FROM stock
GROUP by pid, name
或者

如果
stock\u total
上存在一行,则第一次查询将删除该行,然后插入新行, 第二个查询将更新现有行

只有当表具有主键或唯一索引时,这两个查询才会起作用:

CREATE TABLE stock_total (
    pid         INT         NOT NULL,
    name        VARCHAR(20) NOT NULL,
    total_qty   INT         NOT NULL,

    UNIQUE (pid, name)
);
文件:


哪种品牌的SQL可能重复?MySQL、SQL Server、Oracle等?不同的实现有不同的选项可供选择。我根据OP最初的问题回答了这个问题,然后他将它添加到mysql标签中。但这对甲骨文非常有效。对于mysql,请参阅我的编辑…我认为最终SQL将非常长,带有(HOLDLOCK)
将我吓坏了:)。但是谢谢。我不是SP粉丝,但是回答很好。谢谢Majid,我不熟悉这种语法。我使用SQL Server,如果它能改进查询或答案,请随意编辑我的帖子,并提出您的建议。
更新
不起作用,
插入
错过了
分组依据
。但我明白你的意思。谢谢,谢谢,我把插页修好了。更新时出现了什么错误?
INSERT INTO stock_total
SELECT pid, name, SUM(qty)
FROM stock
GROUP by pid, name
ON DUPLICATE KEY UPDATE total_qty=VALUES(total_qty)
CREATE TABLE stock_total (
    pid         INT         NOT NULL,
    name        VARCHAR(20) NOT NULL,
    total_qty   INT         NOT NULL,

    UNIQUE (pid, name)
);