我有以下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";
答案 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
);