更新第一个表中的行,并在单个查询

时间:2016-07-09 01:23:08

标签: mysql insert-into

我正试图弄清楚如何在更新第二个表中的特定字段时向表中插入行。

假设我有表1(dif):

CREATE TABLE dif
(
    Position INT(10) UNSIGNED PRIMARY KEY NOT NULL AUTO_INCREMENT,
    pKey SMALLINT(3) UNSIGNED NOT NULL,
    Number SMALLINT(3) UNSIGNED DEFAULT 0 NOT NULL
);

ALTER TABLE dif
ADD CONSTRAINT dif_article_pKey_fk
FOREIGN KEY (pKey) REFERENCES article (pKey) ON UPDATE CASCADE;

和表2(article):

CREATE TABLE IF NOT EXISTS article (
  pKey smallint(3) unsigned NOT NULL AUTO_INCREMENT,
  Name varchar(80) COLLATE utf8_roman_ci NOT NULL,
  Number SMALLINT NOT NULL DEFAULT 0
  PRIMARY KEY (pKey)
);

表格文章中填充了一些数据,应该只更新。表“dif”在开头是空的。所以,假设我正在更新“文章”中的字段,如下所示:

UPDATE article SET pKey = 15, Name = SomeName,  Number = 22 WHERE pKey=15;

我可以以某种方式将UPDATE查询与此结合起来吗?

INSERT  INTO  dif (pKey, Number) VALUES (15, 12);

“12”是UPDATE之前和之后“article.Number”之间的差异。

1 个答案:

答案 0 :(得分:1)

不,但您可以创建一个存储过程来执行这两个操作,然后在一个语句中执行它。

create procedure GiveThisABetterName
(
    in pKey int,
    in newNumber int,
    in currentNumber int,
    in newName varchar(100)
)
begin
    update 
        article 
    set 
        Name = newName, Number = newNumber 
    where 
        pKey = pKey;

    insert into dif (pKey, Number) values (pKey, newNumber);
end

我的mysql语法生锈了,但应该很接近。然后当你想执行它时:

call GiveThisABetterName(12, 15, 22, 'Some Name');
编辑:在再次阅读您的问题之后,在我看来,您正在尝试使您的数据模型跟踪审核信息,而这些信息并未设置为自然适应。你有控制模型吗?如果是这样,请考虑这样的事情(请参阅here以获取以下内容的工作示例):

CREATE TABLE IF NOT EXISTS article (
  pKey smallint(3) unsigned NOT NULL AUTO_INCREMENT,
  Name varchar(80) COLLATE utf8_roman_ci NOT NULL,
  PRIMARY KEY (pKey)
);

CREATE TABLE ArticleNumbers
(
    Counter int UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    pKey SMALLINT(3) UNSIGNED NOT NULL,
    Number SMALLINT(3) DEFAULT 0 NOT NULL,
    Difference SMALLINT(3)
);

ALTER TABLE ArticleNumbers
    ADD CONSTRAINT ArticleNumbers_article_pKey_fk
        FOREIGN KEY (pKey) REFERENCES article (pKey) ON UPDATE CASCADE;

可能会添加一些视图以简化操作:

CREATE VIEW GroupedArticleNumbers
as
select pKey, max(Counter) as Counter
from ArticleNumbers
group by pKey;

CREATE VIEW CurrentArticles 
as 
select article.pKey, article.Name, numbers.Number, numbers.Difference 
from article 
left outer join GroupedArticleNumbers filter on article.pKey = filter.pKey
left outer join ArticleNumbers numbers on filter.Counter = numbers.Counter;

由于您现在可以单独跟踪基本记录中的数字,但仍然可以轻松确定当前的数字,现在可以组合更新和插入语句功能。见下文。

首先,一些测试数据:

insert into article (Name) values ('Test');
insert into ArticleNumbers (pKey, Number, Difference) values (1, 10, null);
insert into ArticleNumbers (pKey, Number, Difference) select 1, 20, 20 - Number from CurrentArticles where pKey = 1;
insert into ArticleNumbers (pKey, Number, Difference) select 1, 50, 50 - Number from CurrentArticles where pKey = 1;
insert into ArticleNumbers (pKey, Number, Difference) select 1, 15, 15 - Number from CurrentArticles where pKey = 1;

一旦设置架构的开销已经完成,看看有多好用吗?

获取我们创建的文章的当前数字:

select * from currentarticles where pKey = 1

获取该文章的编号记录:

select * from article
left outer join articlenumbers on article.pkey = articlenumbers.pkey
order by counter asc

如果您愿意搞乱数据模型,可以选择存储过程。

或者,如果您想将触发器用作@Jonathan Leffler建议,那么这样的事情应该有效:

CREATE TABLE article (
 pKey smallint(3) unsigned NOT NULL AUTO_INCREMENT,
  Name varchar(80) COLLATE utf8_roman_ci NOT NULL,
  Number SMALLINT(3) DEFAULT 0 NOT NULL,
  PRIMARY KEY (pKey)
);

CREATE TABLE ArticleNumbers
(
    Counter int UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    pKey SMALLINT(3) UNSIGNED NOT NULL,
    Number SMALLINT(3) DEFAULT 0 NOT NULL,
    Difference SMALLINT(3)
);

delimiter $
create trigger tr_u_article
before update on article
for each row
begin
  insert into ArticleNumbers (pKey, Number, Difference) select old.pKey,     new.Number, new.Number - old.Number
  end;
delimiter ;