PostgreSQL插入并忽略多个列

时间:2017-03-23 08:38:40

标签: sql postgresql insert upsert

我新创建了包含4个唯一字段的表格:nsnslugpart_nomfg_sku

我正在尝试插入此表约。来自多个表的200万行,也有重复的行。

所以主要问题是......

在这种情况下如何模仿insert ignore

根据多列或您的建议选择不同的颜色?

以下是我要插入Part

的数据
 SELECT "PartOld".id,
    "PartOld"."PartNo",
    "PartOld"."Manufacturer",
    "PartOld"."Slug",
    "PartOld"."Description",
    "PartOld"."NSN",
    NULL::numeric AS price,
    "PartOld".name,
    NULL::character varying AS mfg_sku
   FROM "PartOld"
UNION
 SELECT part_item.id,
    NULL::character varying AS "PartNo",
    part_item.manufacturer AS "Manufacturer",
    NULL::character varying AS "Slug",
    part_item.details AS "Description",
    part_item.msn AS "NSN",
    NULL::numeric AS price,
    part_item.name,
    part_item.mfg_sku
   FROM part_item_fetched part_item

这是Part表。

DROP TABLE IF EXISTS "electronic_parts"."Part";
CREATE TABLE "electronic_parts"."Part" (
    "id" int4 NOT NULL DEFAULT nextval('"Part_id_seq"'::regclass),
    "part_no" varchar COLLATE "default",
    "manufacturer" varchar COLLATE "default",
    "description" text COLLATE "default",
    "slug" varchar COLLATE "default",
    "nsn" varchar COLLATE "default",
    "price" numeric,
    "name" varchar COLLATE "default",
    "mfg_sku" varchar COLLATE "default"
)
WITH (OIDS=FALSE);
ALTER TABLE "electronic_parts"."Part" OWNER TO "root";

-- ----------------------------
--  Primary key structure for table Part
-- ----------------------------
ALTER TABLE "electronic_parts"."Part" ADD PRIMARY KEY ("id") NOT DEFERRABLE INITIALLY IMMEDIATE;

-- ----------------------------
--  Indexes structure for table Part
-- ----------------------------
CREATE UNIQUE INDEX  "part_u1" ON "electronic_parts"."Part" USING btree(part_no COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);
CREATE UNIQUE INDEX  "part_u2" ON "electronic_parts"."Part" USING btree(nsn COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);
CREATE UNIQUE INDEX  "part_u3" ON "electronic_parts"."Part" USING btree(mfg_sku COLLATE "default" "pg_catalog"."text_ops" ASC NULLS LAST);

2 个答案:

答案 0 :(得分:0)

使用

INSERT INTO ...
   (SELECT ...)
ON CONFLICT DO NOTHING;

从9.5开始提供此功能,请参阅the documentation

答案 1 :(得分:0)

您可以使用anti joins过滤您的输入(通过NOT EXISTS()LEFT JOIN + IS NULL):

WITH data AS (
  -- your query here
  SELECT ...
  UNION ALL ...
),
conflicting_ids AS (
  SELECT id      FROM data GROUP BY id      HAVING COUNT(*) > 1
),
conflicting_part_nos AS (
  SELECT part_no FROM data GROUP BY part_no HAVING COUNT(*) > 1
),
conflicting_nsns AS (
  SELECT nsn     FROM data GROUP BY nsn     HAVING COUNT(*) > 1
),
conflicting_mfg_skus AS (
  SELECT mfg_sku FROM data GROUP BY mfg_sku HAVING COUNT(*) > 1
)
INSERT INTO table_name (column_names)
SELECT d.*
FROM   data d
WHERE  NOT EXISTS(SELECT 1 FROM conflicting_ids a      WHERE a.id = d.id)
AND    NOT EXISTS(SELECT 1 FROM conflicting_part_nos a WHERE a.part_no = d.part_no)
AND    NOT EXISTS(SELECT 1 FROM conflicting_nsns a     WHERE a.nsn = d.nsn)
AND    NOT EXISTS(SELECT 1 FROM conflicting_mfg_skus a WHERE a.mfg_sku = d.mfg_sku)
ON CONFLICT DO NOTHING

Notes id也是唯一的,因为它是主键。此外,由于单独检查冲突的行,因此您不需要UNION。您可以使用UNION ALL,效率稍高。