【问题标题】:MySQL conditional insert with insert .. selectMySQL 条件插入与 insert .. select
【发布时间】:2018-02-26 14:11:40
【问题描述】:

我有一个电子商务网站,客户可以登录并查看各种产品的价格。每个客户都有自己的价目表,价格可以通过多种方式(来源)设置。下表如下:

CREATE TABLE customer_price_list (
  customer_price_id int(11) NOT NULL AUTO_INCREMENT,
  customer_account_id int(11) NOT NULL,
  product_id int(11) DEFAULT NULL,
  currency_id int(11) DEFAULT NULL,
  customer_price decimal(7,2) DEFAULT NULL,
  source enum('TRADE_DEFAULT','TEMPLATE','SAGE','MANUAL') DEFAULT NULL,
  PRIMARY KEY (customer_price_id),
  KEY customer_account_id (customer_account_id),
  KEY product_id (product_id),
  KEY currency_id (currency_id),
  KEY source (source)
) 

仅取 product_id、customer_price 和 source,一个客户的示例数据可能看起来像(使用字符串作为 product_id 只是为了说明):

Prod_1, 10.00, TRADE_DEFAULT 
Prod_2, 20.00, TRADE_DEFAULT 
Prod_3, 25.00, MANUAL 

还有一个不同的客户:

Prod_1, 7.50, SAGE 
Prod_2, 20.00, TRADE_DEFAULT 
Prod_3, 30.00, TRADE_DEFAULT 

没有折扣的商品的基本价格是当来源为 TRADE_DEFAULT 时 - 上面显示这两个客户各有两件商品的 TRADE_DEFAULT 价格,但在一件商品上获得了折扣。

TRADE_DEFAULT 价格是通过导入包含 product_id、currency_id 和 customer_price 的 CSV 文件来设置的。在 PHP 中,我遍历 CSV 中的所有行并将值绑定到此查询:

insert into customer_price_list  
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source) 
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account

当 customer_price_list 为空时(对于 CSV 中的所有 product_id/currency_id 组合),这可以正常工作。但是,如果某些客户已经有 product_id/currency_id 条目,这将导致额外的行(即该客户的产品将有两个或多个价格)

所以,在处理 CSV 时,我想:

A) 将任何现有 TRADE_DEFAULT 更新为 CSV 中的新值(再次从 CSV 内容的循环中运行)

update  customer_price_list set customer_price = :price
        where currency_id=:currency_id and product_id=:product_id and source ='TRADE_DEFAULT'

B) 如果该客户没有该产品/货币的价格,则插入 TRADE_DEFAULT 价格

insert (ONLY IF NO PRICE OF ANY SOURCE IS THERE) into customer_price_list  
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source) 
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account

这是我需要帮助的地方。我已经搜索了条件插入查询,但我只能找到他们在哪里插入一个这样的记录:

insert into table1 (user,rating,last_modified)
select 'user1', 1999, NOW() from table1
where not exists (
select * from table1
where last_modified > '2007-04-13 08:52:41'
and user='user1'
) limit 1

但如果需要,我想为所有客户插入 .. 选择并插入。

谢谢。

【问题讨论】:

  • 您应该能够将ON DUPLICATE KEY UPDATE 扩展用于插入语句。
  • 谢谢,我根据您的建议发布了答案。

标签: mysql sql


【解决方案1】:

尝试使用合并:

https://docs.microsoft.com/en-us/sql/t-sql/statements/merge-transact-sql

这可能对您的情况有所帮助,因为它允许根据条件插入值并在它们已经存在时进行更新。

【讨论】:

【解决方案2】:

使用@Stavr00 的建议我想出了这个:

首先添加一个跨三列的索引,以使每个客户的产品/货币唯一:

alter table customer_price_list add  UNIQUE INDEX unq_cust_prod (customer_account_id ASC, product_id ASC, currency_id ASC)

然后更改查询:

insert into customer_price_list  
(customer_price_id, customer_account_id, product_id, currency_id, customer_price, source) 
select 0, customer_account_id, :product_id, :currency_id, :price, 'TRADE_DEFAULT' from customer_account
ON DUPLICATE KEY UPDATE customer_price=customer_price;

通过使更新将价格设置为当前值,查询变成了条件插入。当与我的问题中步骤 A 中的更新查询结合使用时,它可以满足我的需求。

我想我可以使用 ON DUPLICATE KEY UPDATE 来完成另一个查询的工作,并在一个查询中完成所有操作。但是,我只想更新 source = TRADE_DEFAULT 的现有记录,所以不知道该怎么做。

另外,我似乎可以使用插入忽略,但由于这不会标记一些真正的错误,如类型不匹配,我认为我的解决方案更安全。

欢迎评论!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 2015-09-20
    • 2013-11-13
    • 2013-07-12
    • 1970-01-01
    • 1970-01-01
    • 2018-12-17
    相关资源
    最近更新 更多