44

我知道在 Postgres pure 中,您可以将整数数组传递给函数,但 .NET 数据提供程序 Npgsql 不支持此功能。

我目前有一个 DbCommand,我在其中加载对存储过程的调用,添加参数并执行标量以获取 Id 以填充对象。

现在需要将 n 个整数作为参数。这些用于创建子记录,通过它的 id 将新创建的记录链接到整数参数。

理想情况下,我宁愿不必为每个整数在我的 DbCommand 上进行多次 ExecuteNonQuery 调用,因此我将构建一个 csv 字符串作为将在数据库端拆分的参数。

我通常生活在 LINQ 2 SQL 中,享受 Db 抽象,在这个项目上使用手动数据访问,这一切都变得有点脏,人们通常如何将这些类型的参数传递给 postgres?

4

4 回答 4

71

见:http ://www.postgresql.org/docs/9.1/static/arrays.html

如果您的非本地驱动程序仍然不允许您传递数组,那么您可以:

  • 传递数组的字符串表示形式(然后您的存储过程可以将其解析为数组——请参阅string_to_array

    CREATE FUNCTION my_method(TEXT) RETURNS VOID AS $$ 
    DECLARE
           ids INT[];
    BEGIN
           ids = string_to_array($1,',');
           ...
    END $$ LANGUAGE plpgsql;
    

    然后

    SELECT my_method(:1)
    

    与:1 ='1,2,3,4'

  • 依赖 Postgres 本身将字符串转换为数组

    CREATE FUNCTION my_method(INT[]) RETURNS VOID AS $$ 
           ...
    END $$ LANGUAGE plpgsql;
    

    然后

    SELECT my_method('{1,2,3,4}')
    
  • 选择不使用绑定变量并发出一个明确的命令字符串,其中包含所有参数的拼写(确保验证或转义来自外部的所有参数,以避免 SQL 注入攻击。)

    CREATE FUNCTION my_method(INT[]) RETURNS VOID AS $$ 
           ...
    END $$ LANGUAGE plpgsql;
    

    然后

    SELECT my_method(ARRAY [1,2,3,4])
    
于 2009-02-20T20:54:55.827 回答
64

我意识到这是一个老问题,但我花了几个小时才找到一个好的解决方案,并认为我会传递我在这里学到的东西并为其他人省去麻烦。试一下,例如,

    SELECT * FROM some_table WHERE id_column = ANY(@id_list)

where@id_list被绑定到一个int[]参数

    command.Parameters.Add("@id_list", NpgsqlDbType.Array|NpgsqlDbType.Integer).Value = my_id_list;

其中 command 是 NpgsqlCommand(在 Visual Studio 中使用 C# 和 Npgsql)。

于 2011-10-11T23:30:12.863 回答
2

始终可以使用格式正确的字符串。诀窍是格式。

command.Parameters.Add("@array_parameter", string.Format("{{{0}}}", string.Join(",", array));

请注意,如果您的数组是一个字符串数组,那么您将需要使用array.Select(value => string.Format("\"{0}\", value))或等效的。我在 PostgreSQL 中将这种样式用于枚举类型的数组,因为数组没有自动转换。

在我的例子中,我的枚举类型有一些值,比如'value1', 'value2', 'value3',而我的 C# 枚举有匹配的值。在我的例子中,最终的 SQL 查询最终看起来像(E'{"value1","value2"}'),这很有效。

于 2013-09-01T23:36:37.483 回答
1

完整的编码结构

PostgreSQL 函数

CREATE OR REPLACE FUNCTION admin.usp_itemdisplayid_byitemhead_select(
    item_head_list int[])
    RETURNS TABLE(item_display_id integer) 
    LANGUAGE 'sql'

    COST 100
    VOLATILE 
    ROWS 1000
    
AS $BODY$ 
        SELECT vii.item_display_id from admin.view_item_information as vii
where vii.item_head_id = ANY(item_head_list);
    $BODY$;

模型

public class CampaignCreator
    {
        public int item_display_id { get; set; }
        public List<int> pitem_head_id { get; set; }
    }

.NET CORE 函数

DynamicParameters _parameter = new DynamicParameters();
                _parameter.Add("@item_head_list",obj.pitem_head_id);
                
                string sql = "select * from admin.usp_itemdisplayid_byitemhead_select(@item_head_list)";
                response.data = await _connection.QueryAsync<CampaignCreator>(sql, _parameter);
于 2021-01-26T05:11:03.853 回答