在单个查询中更新第一个 table 中的行并在第二个 table 中插入一行
Update row in first table and insert a row into a second table in a single query
我正在尝试弄清楚如何在更新第二个 table 中的特定字段时将行插入 table。
假设我有 table 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;
和table 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)
);
table 文章填充了一些数据,应该只更新。 Table "dif"开头是空的。所以,假设我正在像这样更新 "article" 上的字段:
UPDATE article SET pKey = 15, Name = SomeName, Number = 22 WHERE pKey=15;
我能否以某种方式将 UPDATE 查询与此结合起来?
INSERT INTO dif (pKey, Number) VALUES (15, 12);
“12”是 "article.Number" 更新前后的差异。
不,但是您可以创建一个存储过程来执行这两项操作,然后在一条语句中执行它。
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 ;
我正在尝试弄清楚如何在更新第二个 table 中的特定字段时将行插入 table。
假设我有 table 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;
和table 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)
);
table 文章填充了一些数据,应该只更新。 Table "dif"开头是空的。所以,假设我正在像这样更新 "article" 上的字段:
UPDATE article SET pKey = 15, Name = SomeName, Number = 22 WHERE pKey=15;
我能否以某种方式将 UPDATE 查询与此结合起来?
INSERT INTO dif (pKey, Number) VALUES (15, 12);
“12”是 "article.Number" 更新前后的差异。
不,但是您可以创建一个存储过程来执行这两项操作,然后在一条语句中执行它。
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 ;