【问题标题】:Convert INSERT IGNORE to Postgres INSERT将 INSERT IGNORE 转换为 Postgres INSERT
【发布时间】:2017-02-14 00:30:37
【问题描述】:

我目前正在研究一个正则表达式,以在 Postgres 语法上转换 sql 语法。我正在使用 geany 来替换文本。目前,我尝试更改的语法是这样的:

INSERT IGNORE INTO item_question_ (question_fk_,item_fk_) VALUES(1002,162);

进入:

INSERT INTO item_question_ (question_fk_,item_fk_) VALUES (1002,151) 
WHERE NOT EXISTS 
(SELECT 1 FROM item_questionnaire_ WHERE question_fk_=1002 AND item_fk_ = 151)

我很接近,但绝对不够。我有这个正则表达式:

(INSERT IGNORE INTO (.*)_ (.*) VALUES(.*);) //Find information
INSERT INTO \2_ \3 VALUES \4 WHERE NOT EXISTS (SELECT 1 FROM \2_ WHERE )// Transform information

事实上我遗漏了最重要的部分:WHERE 子句。

如何获取值 question_fk_,item_fk_1002,151 来构建我的 where 子句?

附加说明:Postgres 版本低于 9.5。我不能使用ON CONFLICT IGNORE

【问题讨论】:

  • 为什么在这里使用正则表达式?这不是此类转译任务的合适工具。
  • 我需要进行大量翻译,而不是一行。正则表达式似乎是为我做这件事的更合适的方式。但是也许我错了
  • 为什么不升级到 9.5 并使用on conflict ignore
  • 我无法控制 postgres 版本。我无法升级

标签: sql regex postgresql


【解决方案1】:

PostgreSQL 9.5+:将原始查询中的 IGNORE 替换为 ON CONFLICT IGNORE,这是 PostgreSQL 语法,用于在任何约束失败时忽略更新。

【讨论】:

  • 事实是 tmy 客户数据库不在 9.5 版本上
  • @Pierre-AlexandreMoller 然后将这些信息放入您的问题中。
【解决方案2】:

正如其他人提到的,只需使用 Postgres 9.5+ 中的 ON CONFLICT IGNORE。但既然你说数据库版本低于 9.5,这是你的正则表达式解决方案:

INSERT IGNORE INTO (.*) \((.*),(.*)\) VALUES \((.*),(.*)\); // capture

INSERT INTO \1 (\2, \3) VALUES (\4, \5) WHERE NOT EXISTS (SELECT 1 FROM \1 WHERE \2 = \4 AND \3 = \5) // replace

但请记住,此正则表达式仅适用于恰好插入 2 个项目。

【讨论】:

  • 它会完成这项工作,我的查询中只有 2 项。对于我的信息,是否可以轻松扩展此正则表达式以适用于 2 个以上的项目?
  • 什么都没想到。正如我所说,正则表达式不擅长这种转换。此查询是高阶语言,不能被常规语法使用。这需要上下文无关的语法。
  • 翻译文件的所有请求比正则表达式更好吗?
  • 好吧,您可以实现基于 SQL 上下文无关语法的简化解析器,并将一种方言正确编译(转换?)到另一种方言。或者也许已经有合适的工具来完成这项任务?...
【解决方案3】:

在查询末尾添加ON CONFLICT DO NOTHING

【讨论】:

    【解决方案4】:

    使用子查询:

    INSERT INTO item_question_ (question_fk_, item_fk_) 
        SELECT q, i
        FROM (SELECT 1002 as q, 151 as i) t
        WHERE NOT EXISTS (SELECT 1
                          FROM item_questionnaire_ iq
                          WHERE iq.question_fk_= t.q AND iq.item_fk_ = t.i
                         );
    

    这也允许您只输入一次值。

    注意:我注意到被引用的表是不同的。我认为这是故意的,但我认为问题是唯一的约束违规。

    另请注意,自 Postgres 9.5 起,更好的方法是使用 ON CONFLICT IGNORE,但您的问题特别是关于使用 NOT EXISTS

    【讨论】:

    • 我仍然需要找到一种方法来拆分值参数和列名
    • @Pierre-AlexandreMoller 。 . .我看到的问题是“将 INSERT IGNORE 转换为 Postgres INSERT”。
    猜你喜欢
    • 2011-11-05
    • 2010-10-07
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 2015-07-30
    • 1970-01-01
    相关资源
    最近更新 更多