如何编写可以多次运行但只插入一次的查询?

时间:2012-04-26 14:07:14

标签: java sql insert request

我有这个要求

INSERT INTO SERVICEPAYANT_CLIENT (RE_ID, TYPE_DONNEES)
SELECT CLIENT_ID, 160 AS TYPE_DONNEES
FROM    REFERENTIEL r, CLIENT_APPLICATIF ca
WHERE r.ID = ca.ID_REFERENTIEL
AND r.TYPE=1
GROUP BY CLIENT_ID
HAVING COUNT(*)>0;

当我多次执行它时,我多次插入数据但是我希望我的请求只插入一次数据。如果我的数据不在我的表格中,我想插入我的数据。

4 个答案:

答案 0 :(得分:3)

你可以这样做:

INSERT INTO SERVICEPAYANT_CLIENT (RE_ID, TYPE_DONNEES)
SELECT CLIENT_ID, 160 AS TYPE_DONNEES
FROM    REFERENTIEL r, CLIENT_APPLICATIF ca
WHERE r.ID = ca.ID_REFERENTIEL
AND r.TYPE=1
AND NOT EXISTS (
    SELECT * FROM SERVICEPAYANT_CLIENT sp
    WHERE sp.RE_ID = CLIENT_ID AND TYPE_DONNEES = 160)
GROUP BY CLIENT_ID
HAVING COUNT(*)>0;

“AND NOT EXISTS ...”将其限制为返回目标表中尚未存在的行。

答案 1 :(得分:2)

对于这些案例,在几个成熟的DBMS中有一个句子MERGEMERGE同时为INSERTUPDATE

一般语法示例:

     MERGE INTO TABLE_NAME USING table_reference ON (condition)
       WHEN MATCHED THEN
       UPDATE SET column1 = value1 [, column2 = value2 ...]
       WHEN NOT MATCHED THEN
       INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...

像MySQL这样的一些DBMS有自己的语法和相同的想法。 请参阅Wikipedia

中的详情

如果您的DBMS没有发布,那么您可以使用相同的逻辑编写存储过程。

但是在插入之前,存储过程或代码中的任何其他检查都会导致“滞后”,并且操作将变为“非原子”。这意味着有可能在您检查之后和插入之前,另一个事务可以创建重复记录,您将获得意外的重复或删除。为避免这种情况,您必须在此操作之前锁定表,以获得对表的独占访问权限,因为访问序列化会对其造成惩罚。

或者您可以将INSERTSELECT一起使用,如下所示:

    INSERT (field1, ...) INTO table1
    SELECT value1, ...
    FROM DUAL -- put a name of analogue of Oracle's DUAL here
    WHERE NOT EXISTS (
       SELECT 1 
       FROM table1
       WHERE key = :new_key
    )

但据您了解,它不会更新任何内容。

答案 2 :(得分:1)

典型的解决方案是在数据库中使用由定义记录的字段组成的唯一约束来强制执行它。然后,您的Java代码将从数据库中收到错误,告知您它已存在。

答案 3 :(得分:1)

你可以这样做:

INSERT INTO SERVICEPAYANT_CLIENT (RE_ID, TYPE_DONNEES)
SELECT CLIENT_ID, 160 AS TYPE_DONNEES
REFERENTIEL r
JOIN CLIENT_APPLICATIF ca
    ON r.ID = ca.ID_REFERENTIEL
WHERE 
    r.TYPE=1
    AND NOT EXISTS
        (
            SELECT
                NULL
            FROM
                SERVICEPAYANT_CLIENT
            WHERE
                REFERENTIEL.CLIENT_ID=SERVICEPAYANT_CLIENT.RE_ID
        )
GROUP BY CLIENT_ID
HAVING COUNT(*)>0;