Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何在plpgsql中进行变量替换?_Postgresql_Entity Framework Core - Fatal编程技术网

Postgresql 如何在plpgsql中进行变量替换?

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

我有一些复杂的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 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代码的唯一方法是通过以下两种方法:

  • 声明一个函数,然后用参数调用它
  • 当已经在plpgsql块中时,可以调用:
    执行$$INSERT。。。价值($1,$2,$3);$使用3,‘文本值’,5.234



  • 完注:
    作为一名热爱其自由,但转向Postgresql的T-SQL开发人员,我不得不说,最大的区别在于,一方面,T-SQL提供了强大的功能,另一方面,它是一种非常强大的Postgresql风格的SQL。plpgsql很少得到保证。事实上,在一个兆字节的复杂SQL代码库中,我可以在SQL中重写几乎所有plpgsql代码。这就是它与MSSQL风格的SQL相比的强大程度。只是需要一些时间来适应,并与非常丰富的文档交朋友。祝你好运

    谢谢你的好问题。我今天学到了一些新的东西来回答它。太棒了!从现在起,我的经验法则是“找到plpgsql的SQL替代品”。