将MySQL查询转换为PostgreSQL

时间:2011-09-28 16:41:04

标签: mysql sql postgresql

我有这个问题:

DROP TABLE IF EXISTS tmp_table;
CREATE TEMPORARY TABLE tmp_table(id int primary key) 
IGNORE (
   SELECT user2role.userid AS userid
     FROM user2role 
    INNER JOIN users ON users.id=user2role.userid 
    INNER JOIN role ON role.roleid=user2role.roleid 
    WHERE role.parentrole like 'H1::H2::H3::H4::H5::%') 
UNION (
   SELECT groupid
     FROM groups
    WHERE groupid IN (2,3,4));

此查询最初是用MySQL编写的,而不是DROP TABLE IF EXISTS使用IF NOT EXISTS。我改变了那部分,但我不知道如何处理IGNORE

首先,IGNORE在做什么?

我试过寻找PostgreSQL等价物,但它们似乎都涉及复杂的程序。我必须为此编写程序吗?如果我必须写一个,它会是什么样子?我可以使用一些PHP代码来模拟IGNORE吗? (SQL查询由PHP生成。)

1 个答案:

答案 0 :(得分:6)

你会在postgres中这样写。
IGNORE在这里无关紧要,因为该表刚刚被重新创建并且保证为空。并且UNION保证不会插入重复的行。

DROP TABLE IF EXISTS tmp_table;

CREATE TEMP TABLE tmp_table(id int4 primary key);

INSERT INTO tmp_table
SELECT user2role.userid::int4 AS id
  FROM user2role 
  JOIN users ON users.id = user2role.userid 
  JOIN role ON role.roleid = user2role.roleid 
 WHERE role.parentrole like 'H1::H2::H3::H4::H5::%'
UNION
SELECT groupid::int4
  FROM groups
 WHERE groupid in (2,3,4);

如果SELECT中没有重复项,您可能会考虑更快UNION ALL而不是UNION。否则,您需要UNION来消除可能的欺骗行为。阅读here
如果您的数据集很大,您可以考虑在 INSERT之后创建主键。那更快。

阅读IGNORE的效果mySQL docs


在重新访问该页面时,我意识到您在原始代码中提到了IF NOT EXISTS。 你没有这么说,但只有原始代码只有在它已经存在的情况下创建表才有意义,这就引入了INSERT之前不为空的可能性。在这种情况下,IGNORE是相关的,并且在PostgreSQL中需要一个等价物。

因此,对于您的问题的解释, 替代答案

CREATE TEMP TABLE IF NOT EXISTSimplemented in PostgreSQL 9.1 对于旧版本,我最近在SO上发布了solution

CREATE TEMP TABLE IF NOT EXISTS tmp_table(id int4 primary key);

INSERT INTO tmp_table
SELECT x.id
  FROM (
    SELECT user2role.userid::int4 AS id
      FROM user2role 
      JOIN users ON users.id = user2role.userid 
      JOIN role ON role.roleid = user2role.roleid 
     WHERE role.parentrole like 'H1::H2::H3::H4::H5::%'
    UNION
    SELECT groupid::int4
      FROM groups
     WHERE groupid in (2,3,4)
        ) x
  LEFT JOIN tmp_table t USING (id)
 WHERE t.id IS NULL;

LEFT JOIN ... WHERE t.id IS NULL排除id中可能已存在的任何tmp_tableUNION进入子选择,因此该子句只需要应用一次。应该是最快的 More on LEFT JOIN here