由于外键限制导致插入延迟
我正在尝试运行查询:(
INSERT
INTO `ProductState` (`ProductId`, `ChangedOn`, `State`)
SELECT t.`ProductId`, t.`ProcessedOn`, \'Activated\'
FROM `tmpImport` t
LEFT JOIN `Product` p
ON t.`ProductId` = p.`Id`
WHERE p.`Id` IS NULL
ON DUPLICATE KEY UPDATE
`ChangedOn` = VALUES(`ChangedOn`)
我不太确定查询是否正确,但它似乎正在工作),但是我遇到了以下问题。我在创建“产品”表中的条目之前运行此查询,并且由于该条目尚未位于“产品”表中而遇到外键约束问题。
我的问题是,有没有办法运行此查询,但等到下一个查询(更新产品表)后再执行上面查询的插入部分?另请注意,如果在创建产品条目之后运行查询,它将不再将 p.Id
视为空,因此会失败,因此必须在创建产品条目之前执行该查询。
--->编辑<--- 我试图实现的概念如下: 首先,我将一组数据导入到临时表中,Product
表是通过临时表中的数据集添加(或过去)添加的所有产品的列表。我需要的是一个单独的表,它提供产品的状态更改,因为有时产品将变得不可用(不再在供应商提供的数据集中)。
ProductState 表如下:
CREATE TABLE IF NOT EXISTS `ProductState` (
`ProductId` VARCHAR(32) NOT NULL ,
`ChangedOn` DATE NOT NULL ,
`State` ENUM('Activated','Deactivated') NULL ,
PRIMARY KEY (`ProductId`, `ChangedOn`) ,
INDEX `fk_ProductState_Product` (`ProductId` ASC) ,
CONSTRAINT `fk_ProductState_Product`
FOREIGN KEY (`ProductId` )
REFERENCES `Product` (`Id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
外键是与 Product 表的标识关系 (Product
.Id
)
本质上我想要完成的是: 1. 每当供应商数据集中出现新产品(或之前停用的产品)时,都会在 ProductState 表中创建一条记录为“已激活”。 2. 只要产品(已激活)未显示在供应商数据集中,该记录就会在 ProductState 表中创建为“已停用”。
ProductState 表的目的是跟踪产品的激活和停用状态。另外,ProductState 与 Product Table 是多对一的关系,并且产品的状态每天只会更改一次,因此我的 PKEY 将是 ProductId 和 ChangedDate。
I am trying to run a query:
INSERT
INTO `ProductState` (`ProductId`, `ChangedOn`, `State`)
SELECT t.`ProductId`, t.`ProcessedOn`, \'Activated\'
FROM `tmpImport` t
LEFT JOIN `Product` p
ON t.`ProductId` = p.`Id`
WHERE p.`Id` IS NULL
ON DUPLICATE KEY UPDATE
`ChangedOn` = VALUES(`ChangedOn`)
(I am not quite sure the query is correct, but it appears to be working), however I am running into the following issue. I am running this query before creating the entry into the 'Products' table and am getting a foreign key constraint problem due to the fact that the entry is not in the Products table yet.
My question is, is there a way to run this query, but wait until the next query (which updates the Product table) before performing the insert portion of the query above? Also to note, if the query is run after the Product entry is created it will no longer see the p.Id
as being null and therefore failing so it has to be performed before the Product entry is created.
---> Edit <---
The concept I am trying to achieve is as follows:
For starters I am importing a set of data into a temp table, the Product
table is a list of all products that are (or have been in the past) added through the set of data from the temp table. What I need is a separate table that provides a state change to the product as sometimes the product will become unavailable (no longer in the data set provided by the vendor).
The ProductState table is as follows:
CREATE TABLE IF NOT EXISTS `ProductState` (
`ProductId` VARCHAR(32) NOT NULL ,
`ChangedOn` DATE NOT NULL ,
`State` ENUM('Activated','Deactivated') NULL ,
PRIMARY KEY (`ProductId`, `ChangedOn`) ,
INDEX `fk_ProductState_Product` (`ProductId` ASC) ,
CONSTRAINT `fk_ProductState_Product`
FOREIGN KEY (`ProductId` )
REFERENCES `Product` (`Id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;
The foreign key is an identifying relationship with the Product table (Product
.Id
)
Essentially what I am trying to accomplish is this:
1. Anytime a new product (or previously deactivated product) shows up in the vendor data set, the record is created in the ProductState table as 'Activated'.
2. Anytime a product (that is activated), does not show up in the vendor data set, the record is created as 'Deactivated' in the ProductState table.
The purpose of the ProductState table is to track activation and deactivation states of a product. Also the ProductState is a Multi-To-One relationship with the Product Table, and the state of the product will only change once daily, therefore my PKEY would be ProductId and ChangedDate.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有了外键,你肯定需要先有Product表上的数据,在进入状态之前,用这样的逻辑思考:“不存在的东西怎么会有状态”?
因此,您应该执行以下操作的伪代码:
所有这些都应该在 1 个事务中完成。请注意,您不应该从 Product 表中删除内容,除非您确实想删除与其关联的所有信息,即。还要删除您存储的所有“状态”。
最好的办法是创建一个存储过程,按照上面的步骤逐步完成工作,而不是尝试在一个查询中完成所有这些工作。我认为在一个查询中完成所有操作会变得过于复杂(或者在这种情况下,可能是不可能的)。
编辑:像这样的东西:
With foreign keys, you definitely need to have the data on the Product table first, before entering the state, think about it with this logic: "How can something that dont exist have a state" ?
So pseudocode of what you should do:
All these should be done in 1 transaction. Note that you should NOT delete things from Product table, unless you really want to delete every information associated with it, ie. also delete all the "states" that you have stored.
Rather than trying to do this all in 1 query - best bet is to create a stored procedure that does the work as step-by-step above. I think it gets overly complicated (or in this case, probably impossible) to do all in 1 query.
Edit: Something like this:
我认为你应该:
Products
表中ProductState
表中这将避免任何外键错误,但也会确保您的数据始终准确。您不想以任何方式“避免”外键约束,并且 InnoDB(我确定您正在使用)永远不会推迟这些约束,除非您完全关闭它们。
另外,您不能在一个 INSERT ... SELECT 语句中插入多个表。
I think you should:
Products
tableProductState
tableThis will avoid any foreign key errors, but will also make sure your data is always accurate. You do not want to 'avoid' the foreign key constraint in any way, and InnoDB (which I'm sure you are using) never defers these constraints unless you turn them off completely.
Also no you cannot insert into multiple tables in one INSERT ... SELECT statement.