PostgreSQL相当于IF @@ ROWCOUNT = 0 INSERT INTO

时间:2017-05-10 14:34:03

标签: c# sql sql-server postgresql

我有以下SQL查询(以C#字符串SqlCommand命令格式),它将尝试更新记录,如果它不存在,则改为INSERT。

string query = @"UPDATE [schemaX].[tableY] SET
                GUID = @GUID,
                Platform = @Platform,
                Email = @Email
                WHERE Email = @Email AND Platform = @Platform

                IF @@ROWCOUNT=0 INSERT INTO [schemaX].[tableY]
                (
                    GUID,
                    Platform,
                    Email
                )
                Values
                (
                    @GUID,
                    @Platform,
                    @Email
                )";

tableY列:

Id:int (Primary Key auto increment)
Email: string
GUID:string
Platform:string

我正在尝试将其转换为PostgreSQL查询(NpgsqlCommand命令)

似乎有许多建议使用UPSERT ON CONFLICT或WHERE NOT EXISTS但我无法看到我在这种情况下如何使用它,因为我从来不知道或设置主键字段Id以确定是否存在CONFLICT ,Id是自动生成的字段。 PostgreSQL似乎首先检查INSERT冲突而不是UPDATE。

我如何在PostgreSQL中执行此操作?

例如,下面的查询会创建多个记录,而不是使用相同的电子邮件平台

更新现有记录

注意:理想情况下,我可以将GUID更改为主键并使其正常工作,但由于其他原因,我无法在此情况下更改表。

string query = @"INSERT INTO ""schemaX"".""tableY""
                (
                    ""GUID"",
                    ""Platform"",
                    ""Email""
                )
                Values
                (
                    @GUID,
                    @Platform,
                    @Email

                )
                ON CONFLICT (""Id"") DO
                UPDATE SET
                ""GUID"" = @GUID,
                ""Platform"" = @Platform,
                ""Email"" = @Email
                WHERE ""schemaX"".""tableY"".""Email"" = @Email AND ""schemaX"".""tableY"".""Platform"" = @Platform";

2 个答案:

答案 0 :(得分:3)

您原始查询的PostgreSQL等效项是:

INSERT INTO "schemaX"."tableY" ("GUID", "Platform", "Email")
  VALUES (@GUID, @Platform, @Email)
  ON CONFLICT ("Platform", "Email")
  DO UPDATE SET "GUID" = EXCLUDED."GUID"

您不需要更新"Platform""Email",因为它们定义了您想要实现的唯一性(因此,如果达到ON CONFLICT分支,则已经存在表中的一行,具有完全相同的值)。你也不需要DO UPDATE的谓词:无论如何因为这个唯一性。 EXCLUDED"行"是避免重复查询参数的简单方法。当UPSERT基于INSERT INTO ... SELECT ...声明时,更为重要。

但是,PostgreSQL将在("Platform", "Email")上要求一个唯一约束(或至少一个唯一索引),以保证此查询的成功。

答案 1 :(得分:0)

您也可以使用EXISTS子句执行此操作:

INSERT INTO [schemaX].[tableY] (  GUID,  Platform,  Email )
VALUES                         ( @GUID, @Platform, @Email )
WHERE NOT EXISTS (
    SELECT  1
    FROM    [schemaX].[tableY]
    WHERE   Email = @Email
    AND     Platform = @Platform
);