2011-04-06 32 views
0

我有以下INSERT从SELECT处插入INSERT - 如果存在?

INSERT INTO `tbl_productcategorylink` 
(`pcl_p_id`, `pcl_cat_id`, `pcl_orderby`) 
    SELECT 
    `p_id` AS pcl_p_id, 
    (SELECT `cat_id` FROM `tbl_categories` WHERE 
     CASE 
      WHEN `tbl_products`.`p_gender` = 'female' THEN 
       `cat_url_tag` = 'womens' 
      ELSE 
      `cat_url_tag` = 'mens' 
     END 
    LIMIT 1) AS pcl_cat_id, 
    1 AS pcl_orderby 
FROM `tbl_products` 
WHERE `tbl_products`.`p_gender` = 'female' OR `tbl_products`.`p_gender` = 'male'; 

这是添加链接类别和产品之间,p_gender设定为“男性”任何产品都加入到“男子”类别,同样为“女'类。

如何才能做到这一点,但只有当某一行尚不存在给定的产品?

我基本上需要的东西添加到我的WHERE条款,以确定是否已存在某行:

AND `exists` IS NULL 

我试图创建查询的SELECT部分原因exists列,但是这会搞砸列数并使INSERT失败。

对此有何建议?

谢谢。

回答

3
INSERT 
    tbl_productcategorylink 
    (pcl_p_id, pcl_cat_id, pcl_orderby) 
SELECT 
    p.p_id, c.cat_id, 1 
FROM 
    tbl_products p 
    INNER JOIN tbl_categories c ON c.cat_url_tag = CASE p.p_gender 
               WHEN 'female' THEN 'womens' 
               ELSE 'mens' END 
WHERE 
    p.p_gender IN ('female', 'male') 
    AND NOT EXISTS (
    SELECT 1 FROM tbl_productcategorylink WHERE pcl_p_id = p.p_id 
) 
+0

非常漂亮托默勒格 - 感谢 – 2011-04-07 08:22:44

+0

略有修改到'不EXISTS'是这样的'AND pcl_cat_id = C。作为产品的cat_id'可能已经在表tbl_productcategorylink中,但是在另一个类别中。再次感谢。 – 2011-04-07 10:11:43

+0

@jakenoble:是的,我想添加类似的东西,但后来决定我无法确定这对你是对还是错。显然,你可以自己弄清楚。 :-)我的观点更多的是你可以加入表达式,这使得SQL语句比原来的语句简单和直接。 – Tomalak 2011-04-07 16:47:53

1

尝试不要在where子句中存在:

INSERT INTO `tbl_productcategorylink` 
(`pcl_p_id`, `pcl_cat_id`, `pcl_orderby`) 
    SELECT 
    `p_id` AS pcl_p_id, 
    (SELECT `cat_id` FROM `tbl_categories` WHERE 
     CASE 
      WHEN `tbl_products`.`p_gender` = 'female' THEN 
       `cat_url_tag` = 'womens' 
      ELSE 
      `cat_url_tag` = 'mens' 
     END 
    LIMIT 1) AS pcl_cat_id, 
    1 AS pcl_orderby 
FROM `tbl_products` 
WHERE `tbl_products`.`p_gender` = 'female' OR `tbl_products`.`p_gender` = 'male' 
    AND NOT EXISTS (SELECT * FROM `tbl_productcategorylink` WHERE `pcl_p_id` = `tbl_products`.`p_id`); 
1

你可以使用INSERT IGNORE继续如果键存在。假设列上有一个唯一的键。

0

当稍后重新执行相同的SQL时,“Insert Ignore”效率不高,因为它将尝试重新插入所有记录。您必须限制尝试插入尽可能最小的数量,以获得最佳系统性能。

使用子选择查询的效率也很低,使用大型数据集时“LEFT JOIN”几乎总是更快。子选择查询在SELECT子句中变得可怕。在LEFT JOINed表的字段周围的SELECT子句中使用'IFNULL()',为缺失/ NULL记录提供默认值。

Tomalak的答案很有用,但这是一个纯粹的'LEFT JOIN'示例。

INSERT INTO tbl_productcategorylink (p_pid, pcl_cat_id, pcl_orderby) 
SELECT prod.p_pid, IFNULL(cat.cat_id,0), 1 AS pcl_orderby 
    FROM tbl_products     AS prod 
    LEFT JOIN tbl_categories   AS cat ON cat.cat_url_tag = IF(prod.p_gender='female','womans','mens') 
    LEFT JOIN tbl_productcategorylink AS pcl ON pcl.pcl_p_id = prod.p_id 
WHERE prod.p_gender IN ('female','male') 
    AND pcl.pcl_p_id IS NULL -- Optimizes to faster "NOT EXISTS IN (Select ... From pcl)" 

这个重写是假设tbl_categories有2个特定的记录:'womans'和'mens'。 请注意,'where'子句包含“pcl_p_pid IS NULL”,它在处理非常大的数据集时优化为“NOT EXISTS IN(选择*来自tbl_productcategorylink ...)”的更快版本。

子选择查询执行以下两项操作之一:
a)创建一个临时表。
b)当数据库遍历主'From'表时,执行'查找'到可能存在的每个记录的子选择表中。当子选择在'SELECT'子句中时,这被夸大成可怕的表现。

LEFT JOIN使用数据库提供的已有效的JOIN逻辑,并允许缺少记录。

- J·乔根森 -