当更新记录时,查询不会返回"没有受影响的行"

时间:2017-01-06 05:26:07

标签: sql postgresql

我编写了一个查询记录存在的查询,如果条件为真,则会更新,否则会插入新记录。 问题是插入时,它返回Query returned successfully: 1 rows affected, 200ms execution time.

但更新时返回"查询成功返回:0行受影响,190毫秒执行时间。"但值正确更新。

这是创建表的示例脚本

CREATE TABLE sample
(
  templateid integer NOT NULL DEFAULT nextval('checktemplate_language_lookup_seq'::regclass),
  languageid integer NOT NULL,
  templatetitle character varying(100),
  disclaimer text,
  createdby integer NOT NULL,
  createdtimestamp timestamp without time zone NOT NULL DEFAULT ('now'::text)::timestamp without time zone,
  updatedby integer,
  updatedtimestamp timestamp without time zone,
  CONSTRAINT sample_templateid_languageid UNIQUE (templateid, languageid)
)

在表格中插入新记录:

WITH new_values (templateId, languageId, templatetitle, disclaimer, createdby,createdtimestamp,updatedby,updatedtimestamp)
    AS (
        VALUES (1, 1, 'LangTemplateTitle1', 'LangDisclaimer1', 1,current_timestamp,1,current_timestamp)
        ), upsert
    AS (
        UPDATE sample m
        SET templatetitle = nv.templatetitle, disclaimer = nv.disclaimer, updatedby = nv.updatedby, updatedTimeStamp = nv.updatedtimestamp
        FROM new_values nv
        WHERE m.templateId = nv.templateId AND m.languageId = nv.languageId RETURNING m.*
        )
    INSERT INTO sample (templateId, languageId, templatetitle, disclaimer, createdby,createdtimestamp)
    SELECT templateId, languageId, templatetitle, disclaimer, createdby ,createdtimestamp
    FROM new_values
    WHERE NOT EXISTS (
            SELECT 1
            FROM upsert up
            WHERE up.templateId = new_values.templateId AND up.languageId = new_values.languageId
            )

使用不同的值更新同一行:(更新相同的查询值)

WITH new_values (templateId, languageId, templatetitle, disclaimer, createdby,createdtimestamp,updatedby,updatedtimestamp)
    AS (
        VALUES (1, 1, 'LangTemplateTitle2', 'LangDisclaimer2', 1,current_timestamp,1,current_timestamp)
        ), upsert
    AS (
        UPDATE sample m
        SET templatetitle = nv.templatetitle, disclaimer = nv.disclaimer, updatedby = nv.updatedby, updatedTimeStamp = nv.updatedtimestamp
        FROM new_values nv
        WHERE m.templateId = nv.templateId AND m.languageId = nv.languageId RETURNING m.*
        )
    INSERT INTO sample (templateId, languageId, templatetitle, disclaimer, createdby,createdtimestamp)
    SELECT templateId, languageId, templatetitle, disclaimer, createdby ,createdtimestamp
    FROM new_values
    WHERE NOT EXISTS (
            SELECT 1
            FROM upsert up
            WHERE up.templateId = new_values.templateId AND up.languageId = new_values.languageId
            )

我如何得到"没有行影响价值"即使我使用相同的查询进行更新

1 个答案:

答案 0 :(得分:0)

默认PG行为是仅返回与最终语句相关的消息,在这种情况下始终是INSERT语句,即使UPDATE实际完成了工作,{{1语句什么都不做。如果要自定义消息,则必须将此语句转换为PL / pgSQL函数,您可以INSERT使用自己设计的消息。

也就是说,如果你使用 PG 9.5 + ,你可以使用RAISE NOTICE的{​​{1}}子句来获得更清晰的声明:

ON CONFLICT

请注意最后两个INSERT分配:指定引用和插入时间,但是当更新发生时,这些值将成为更新引用和时间。 INSERT INTO sample (templateId, languageId, templatetitle, disclaimer, createdby, createdtimestamp) VALUES (1, 1, 'LangTemplateTitle1', 'LangDisclaimer1', 1,current_timestamp) ON CONFLICT (templateId, languageId) DO UPDATE SET templatetitle = EXCLUDED.templatetitle, disclaimer = EXCLUDED.disclaimer, updatedby = EXCLUDED.createdby, updatedTimeStamp = EXCLUDED.createdtimestamp; 引用其值导致冲突的行,在本例中是SET子句中的值。

即使您使用的是 PG9.4 ,也可以使用EXCLUDED信息而不是代价高昂的VALUES改进查询:

RETURNING *

这利用了如果WHERE EXISTS没有发生,WITH nv (templateId, languageId, templatetitle, disclaimer, opBy, opTimestamp) AS ( VALUES (1, 1, 'LangTemplateTitle2', 'LangDisclaimer2', 1, current_timestamp) ), upsert AS ( UPDATE sample m SET templatetitle = nv.templatetitle, disclaimer = nv.disclaimer, updatedby = nv.opBy, updatedTimeStamp = nv.opTimestamp FROM nv WHERE m.templateId = nv.templateId AND m.languageId = nv.languageId RETURNING m.* ) INSERT INTO sample (templateId, languageId, templatetitle, disclaimer, createdby, createdtimestamp) SELECT nv.templateId, nv.languageId, nv.templatetitle, nv.disclaimer, nv.opBy, nv.opTimestamp FROM nv, upsert WHERE upsert.templateId IS NULL; 返回所有空值的事实。另请注意使用UPDATERETURNING *来进一步简化语句。