我使用Python写postgres数据库:

sql_string = "INSERT INTO hundred (name,name_slug,status) VALUES ("
sql_string += hundred + ", '" + hundred_slug + "', " + status + ");"
cursor.execute(sql_string)

但由于我的一些行是相同的,我得到以下错误:

psycopg2.IntegrityError: duplicate key value  
  violates unique constraint "hundred_pkey"

我怎么能写一个'插入,除非这行已经存在' SQL语句?

我见过这样的复杂语句:

IF EXISTS (SELECT * FROM invoices WHERE invoiceid = '12345')
UPDATE invoices SET billed = 'TRUE' WHERE invoiceid = '12345'
ELSE
INSERT INTO invoices (invoiceid, billed) VALUES ('12345', 'TRUE')
END IF

但首先,这对我需要的东西来说是不是太过了,其次,我怎么能把它们作为一个简单的字符串来执行呢?


当前回答

获得最多赞的方法(来自John Doe)在某种程度上对我有用,但在我的情况下,从预期的422行中,我只得到180行。 我找不到任何错误,根本没有错误,所以我寻找一个不同的简单的方法。

在SELECT之后使用IF NOT FOUND THEN对我来说是完美的。

(在PostgreSQL文档中描述)

来自文档的例子:

SELECT * INTO myrec FROM emp WHERE empname = myname;
IF NOT FOUND THEN
  RAISE EXCEPTION 'employee % not found', myname;
END IF;

其他回答

你可以在Postgres中使用VALUES:

INSERT INTO person (name)
    SELECT name FROM person
    UNION 
    VALUES ('Bob')
    EXCEPT
    SELECT name FROM person;

您的列“hundred”似乎被定义为主键,因此必须是唯一的,但事实并非如此。问题不在于你,而在于你的数据。

我建议您插入一个id作为串行类型来处理主键

如果你说你的许多行是相同的,你将结束检查很多次。您可以发送它们,数据库将确定是否使用ON CONFLICT子句插入它,如下所示

  INSERT INTO Hundred (name,name_slug,status) VALUES ("sql_string += hundred  
  +",'" + hundred_slug + "', " + status + ") ON CONFLICT ON CONSTRAINT
  hundred_pkey DO NOTHING;" cursor.execute(sql_string);

我怎么能写一个'插入,除非这行已经存在' SQL语句?

在PostgreSQL中有一个很好的方法来执行有条件的INSERT:

INSERT INTO example_table
    (id, name)
SELECT 1, 'John'
WHERE
    NOT EXISTS (
        SELECT id FROM example_table WHERE id = 1
    );

注意:对于并发写操作,这种方法不是100%可靠的。在NOT EXISTS反半连接中的SELECT和INSERT本身之间有一个非常小的竞争条件。在这种情况下,它可能会失败。

这正是我所面临的问题,我的版本是9.5

我用下面的SQL查询来解决它。

INSERT INTO example_table (id, name)
SELECT 1 AS id, 'John' AS name FROM example_table
WHERE NOT EXISTS(
            SELECT id FROM example_table WHERE id = 1
    )
LIMIT 1;

希望这能帮助那些在>= 9.5版本有同样问题的人。

感谢阅读。