Postgresql 如何在plpgsql中进行变量替换?
我有一些复杂的sql代码,我正在从MSSql转换到Postgres(使用Entity Framework Core 2.1),以便在插入到具有唯一索引的表时处理潜在的竞争条件。以下是简化的版本:Postgresql 如何在plpgsql中进行变量替换?,postgresql,entity-framework-core,Postgresql,Entity Framework Core,我有一些复杂的sql代码,我正在从MSSql转换到Postgres(使用Entity Framework Core 2.1),以便在插入到具有唯一索引的表时处理潜在的竞争条件。以下是简化的版本: const string QUERY = @" DO $$ BEGIN insert into Foo (Field1,Field2,Field3) values (@value1,@value2,@value3); EXCEPTION WHEN othe
const string QUERY = @"
DO
$$
BEGIN
insert into Foo (Field1,Field2,Field3)
values (@value1,@value2,@value3);
EXCEPTION WHEN others THEN
-- do nothing; it's a race condition
END;
$$ LANGUAGE plpgsql;
select *
from Foo
where Field1 = @value1
and Field2 = @value2;
";
return DbContext.Foos
.FromSql(QUERY,
new NpgsqlParameter("value1", value1),
new NpgsqlParameter("value2", value2),
new NpgsqlParameter("value3", value3))
.First();
换句话说,尝试插入记录,但如果尝试插入记录导致唯一索引冲突(索引位于Field1+Field2上),则不要引发异常,并返回记录,无论它是由我还是其他线程创建的
这个概念在MSSql中运行良好,使用了TRY..CATCH
块。据我所知,处理Postgres异常的方法与我在plpgsql块中所做的一样
但是…
plpgsql块中的变量替换似乎不起作用。上面的代码在.First()
上失败(顺序中没有元素),当我注释掉异常
行时,我看到了真正的问题,即:
Npgsql.postgresception:42703:列“value1”不存在
当我使用常规Sql进行测试时,也就是说,在不使用plpgsql块的情况下执行insert
,这样做很好
那么,在plpgsql块中进行变量替换的正确方法是什么呢?这不起作用的原因是
do
语句的主体实际上是一个字符串,一个文本
$$
只是在postgresql中分隔文本的另一种方法。它也可以替换为”
或$something$
由于它是一个字符串,Npgsql和Postgresql没有理由在其中混用@value1
解决方案?只有一个非常丑陋的,所以不要使用这个结构,因为你不能传递任何值。处理字符串连接与在C#中进行连接没有什么不同
备选方案
您不需要在plpgsql块中处理异常。只需插入,使用冲突上的,什么都不做
,就可以上路了
INSERT INTO Foo (Field1,Field2,Field3)
VALUES (@value1,@value2,@value3)
ON CONFLICT DO NOTHING;
select *
from Foo
where Field1 = @value1
and Field2 = @value2;
或者如果您真的想继续使用plpgsql,您可以简单地使用提交时的拖放
选项,将这些参数填充为一行,然后在DO
语句中使用它。要使其工作,所有代码都必须作为的一部分执行。为了以防万一,您可以显式地使用一个
将参数传递给plpgsql代码的唯一方法是通过以下两种方法:
执行$$INSERT。。。价值($1,$2,$3);$使用3,‘文本值’,5.234代码>
完注:
作为一名热爱其自由,但转向Postgresql的T-SQL开发人员,我不得不说,最大的区别在于,一方面,T-SQL提供了强大的功能,另一方面,它是一种非常强大的Postgresql风格的SQL。plpgsql很少得到保证。事实上,在一个兆字节的复杂SQL代码库中,我可以在SQL中重写几乎所有plpgsql代码。这就是它与MSSQL风格的SQL相比的强大程度。只是需要一些时间来适应,并与非常丰富的文档交朋友。祝你好运 谢谢你的好问题。我今天学到了一些新的东西来回答它。太棒了!从现在起,我的经验法则是“找到plpgsql的SQL替代品”。