Inserting data with parameters to PostgreSQL 16 [closed]

I’m trying to insert data with parameters to PostgreSQL 16 in C#. I have the following code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>using (var myConnection = new NpgsqlConnection(myConnectionString))
{
myConnection.Open();
var insertAllData = $@"
DO $$
DECLARE
new_production_item_id INTEGER;
BEGIN
INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc)
VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
RETURNING Id INTO new_production_item_id;
INSERT INTO public.some_other_table (some_other_table_id, some_additional_table)
VALUES (new_production_item_id, @SomeAdditionalTableValue);
END $$;
";
using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection))
{
insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("MyTypeId", (int)DataTypeEnum.SomeTypeId) { NpgsqlDbType = NpgsqlDbType.Integer });
insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("CreatedBy", (int)400) { NpgsqlDbType = NpgsqlDbType.Integer });
insertAllDataCommand.Parameters.Add(new NpgsqlParameter<DateTime>("CreationTimeUtc", (new DateTime(2018,1,1,12,0,0)).ToUniversalTime()) { NpgsqlDbType = NpgsqlDbType.TimestampTz });
insertAllDataCommand.ExecuteNonQuery();
}
}
</code>
<code>using (var myConnection = new NpgsqlConnection(myConnectionString)) { myConnection.Open(); var insertAllData = $@" DO $$ DECLARE new_production_item_id INTEGER; BEGIN INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc) VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc) RETURNING Id INTO new_production_item_id; INSERT INTO public.some_other_table (some_other_table_id, some_additional_table) VALUES (new_production_item_id, @SomeAdditionalTableValue); END $$; "; using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection)) { insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("MyTypeId", (int)DataTypeEnum.SomeTypeId) { NpgsqlDbType = NpgsqlDbType.Integer }); insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("CreatedBy", (int)400) { NpgsqlDbType = NpgsqlDbType.Integer }); insertAllDataCommand.Parameters.Add(new NpgsqlParameter<DateTime>("CreationTimeUtc", (new DateTime(2018,1,1,12,0,0)).ToUniversalTime()) { NpgsqlDbType = NpgsqlDbType.TimestampTz }); insertAllDataCommand.ExecuteNonQuery(); } } </code>
using (var myConnection = new NpgsqlConnection(myConnectionString))
{
    myConnection.Open();

    var insertAllData = $@"
        DO $$
        DECLARE
            new_production_item_id INTEGER;
        BEGIN
            INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc)
            VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
            RETURNING Id INTO new_production_item_id;

            INSERT INTO public.some_other_table (some_other_table_id, some_additional_table)
            VALUES (new_production_item_id, @SomeAdditionalTableValue);
        END $$;
    ";

    using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection))
    {
        insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("MyTypeId", (int)DataTypeEnum.SomeTypeId) { NpgsqlDbType = NpgsqlDbType.Integer });
        insertAllDataCommand.Parameters.Add(new NpgsqlParameter<int>("CreatedBy", (int)400) { NpgsqlDbType = NpgsqlDbType.Integer });
        insertAllDataCommand.Parameters.Add(new NpgsqlParameter<DateTime>("CreationTimeUtc", (new DateTime(2018,1,1,12,0,0)).ToUniversalTime()) { NpgsqlDbType = NpgsqlDbType.TimestampTz });

        insertAllDataCommand.ExecuteNonQuery();
    }
}

However, I receive

Npgsql.PostgresException: ‘42703: column “mytypeid” does not exist’

It surprises me because it means that parameter @MyTypeId is considered as a column, rather than as a parameter.

I have also tried changing the @ sign to a : sign. I have tried changing from upper cased table and column names (as was previously) to lower case names with underscore (as it is in the code shown). None of these helped.

I need transaction because the code is in fact more complex, this is just simplified version of what I have.

What is the correct way to add parameters in PostgreSQL in C# so that they are considered as parameters, rather than column names?

As suggested in the comments, I have also tried:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection)
{
Parameters =
{
new("MyTypeId", (int)DataTypeEnum.SomeTypeId),
new("CreatedBy", 400),
new("CreationTimeUtc", (new DateTime(2018, 1, 1, 12, 0, 0)).ToUniversalTime())
}
})
{
insertAllDataCommand.ExecuteReader();
}
</code>
<code>using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection) { Parameters = { new("MyTypeId", (int)DataTypeEnum.SomeTypeId), new("CreatedBy", 400), new("CreationTimeUtc", (new DateTime(2018, 1, 1, 12, 0, 0)).ToUniversalTime()) } }) { insertAllDataCommand.ExecuteReader(); } </code>
using (var insertAllDataCommand = new NpgsqlCommand(insertAllData, myConnection)
{
    Parameters =
    {
        new("MyTypeId", (int)DataTypeEnum.SomeTypeId),
        new("CreatedBy", 400),
        new("CreationTimeUtc", (new DateTime(2018, 1, 1, 12, 0, 0)).ToUniversalTime())
    }
})
{
    insertAllDataCommand.ExecuteReader();
}

But it leads to the same error.

25

I have solved my issue by using:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>string insertAllData = @"
BEGIN;
INSERT INTO production_items (my_data_type_id, created_by, creation_time_utc)
VALUES (@MyDataTypeId, @CreatedBy, @CreationTimeUtc)
RETURNING id;
INSERT INTO Some_Other_Table (My_Item_Id, Work_Plan_Id)
VALUES (currval(pg_get_serial_sequence('production_items', 'id')), @WorkPlanId);
COMMIT;
";
</code>
<code>string insertAllData = @" BEGIN; INSERT INTO production_items (my_data_type_id, created_by, creation_time_utc) VALUES (@MyDataTypeId, @CreatedBy, @CreationTimeUtc) RETURNING id; INSERT INTO Some_Other_Table (My_Item_Id, Work_Plan_Id) VALUES (currval(pg_get_serial_sequence('production_items', 'id')), @WorkPlanId); COMMIT; "; </code>
string insertAllData = @"
    BEGIN;

    INSERT INTO production_items (my_data_type_id, created_by, creation_time_utc)
    VALUES (@MyDataTypeId, @CreatedBy, @CreationTimeUtc)
    RETURNING id;

    INSERT INTO Some_Other_Table (My_Item_Id, Work_Plan_Id)
    VALUES (currval(pg_get_serial_sequence('production_items', 'id')), @WorkPlanId);
    
    COMMIT;
";

Basically, I use currval(pg_get_serial_sequence('production_items', 'id') to get the value inserted in the previous block.

3

We can’t really help without the real query. The problem is in that query, not PostgreSQL or NpgSQL. If PostgreSQL complains about mytypeid it means the real SQL query contains exactly this string, without the @ prefix or title-casing. As it is, the question’s code contains several problems, beyond the query itself.

The Parameters and Positional and Named Placeholders paragraphs in NpgSQL’s Basic Usage page show how easy it is to execute an INSERT with parameters.

Using positional parameters ($1, $2):

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES ($1), ($2)", conn)
{
Parameters =
{
new() { Value = "some_value" },
new() { Value = "some_other_value" }
}
};
await cmd.ExecuteNonQueryAsync();
</code>
<code>await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES ($1), ($2)", conn) { Parameters = { new() { Value = "some_value" }, new() { Value = "some_other_value" } } }; await cmd.ExecuteNonQueryAsync(); </code>
await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES ($1), ($2)", conn)
{
    Parameters =
    {
        new() { Value = "some_value" },
        new() { Value = "some_other_value" }
    }
};

await cmd.ExecuteNonQueryAsync();

Or named parameters (p1, p2). The parameter name definitions do not contain the @ prefix

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES (@p1), (@p2)", conn)
{
Parameters =
{
new("p1", "some_value"),
new("p2", "some_other_value")
}
};
await cmd.ExecuteNonQueryAsync();
</code>
<code>await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES (@p1), (@p2)", conn) { Parameters = { new("p1", "some_value"), new("p2", "some_other_value") } }; await cmd.ExecuteNonQueryAsync(); </code>
await using var cmd = new NpgsqlCommand("INSERT INTO table (col1) VALUES (@p1), (@p2)", conn)
{
    Parameters =
    {
        new("p1", "some_value"),
        new("p2", "some_other_value")
    }
};

await cmd.ExecuteNonQueryAsync();

In both cases, RETURNING id can be used to return an auto-generated ID value. To read it, ExecuteReader or ExecuteReaderAsync should be used :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var sql="""
INSERT INTO table (col1)
VALUES
(@p1),
(@p2)
RETURNING id;
""";
await using var cmd = new NpgsqlCommand(sql, conn)
{
Parameters =
{
new("p1", "some_value"),
new("p2", "some_other_value")
}
};
using var reader=await cmd.ExecuteNonQueryAsync();
while(reader.Read())
{
var id=reader.GetInt32(0);
...
}
</code>
<code>var sql=""" INSERT INTO table (col1) VALUES (@p1), (@p2) RETURNING id; """; await using var cmd = new NpgsqlCommand(sql, conn) { Parameters = { new("p1", "some_value"), new("p2", "some_other_value") } }; using var reader=await cmd.ExecuteNonQueryAsync(); while(reader.Read()) { var id=reader.GetInt32(0); ... } </code>
var sql="""
        INSERT INTO table (col1) 
        VALUES 
            (@p1),
            (@p2)
        RETURNING id;
        """;

await using var cmd = new NpgsqlCommand(sql, conn)
{
    Parameters =
    {
        new("p1", "some_value"),
        new("p2", "some_other_value")
    }
};

using var reader=await cmd.ExecuteNonQueryAsync();
while(reader.Read())
{
    var id=reader.GetInt32(0);
    ...
}

Adopting this to the question’s query would look like this :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var sql="""
INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc)
VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
RETURNING Id;
""";
await using var cmd = new NpgsqlCommand(sql, conn)
{
Parameters =
{
new("MyTypeId", (int)DataTypeEnum.SomeTypeId),
new("CreatedBy", 400),
new("CreationTimeUtc",new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc)
}
};
using var reader=await cmd.ExecuteNonQueryAsync();
...
</code>
<code>var sql=""" INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc) VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc) RETURNING Id; """; await using var cmd = new NpgsqlCommand(sql, conn) { Parameters = { new("MyTypeId", (int)DataTypeEnum.SomeTypeId), new("CreatedBy", 400), new("CreationTimeUtc",new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc) } }; using var reader=await cmd.ExecuteNonQueryAsync(); ... </code>
var sql="""
        INSERT INTO public.production_items (my_data_type_id, created_by, creation_time_utc)
        VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
        RETURNING Id;
        """;

await using var cmd = new NpgsqlCommand(sql, conn)
{
    Parameters =
    {
        new("MyTypeId", (int)DataTypeEnum.SomeTypeId),
        new("CreatedBy", 400),
        new("CreationTimeUtc",new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc)
    }
};

using var reader=await cmd.ExecuteNonQueryAsync();
...

In this case, since only one row is inserted, ExecuteScalar can be used to get the single result value:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var newId=await cmd.ExecuteScalarAsync();
</code>
<code>var newId=await cmd.ExecuteScalarAsync(); </code>
var newId=await cmd.ExecuteScalarAsync();

This can be simplified to a single line using eg Dapper, to create the entire command and parameters automatically, from a parameter object’s properties:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var theParams=new {
MyTypeId=DataTypeEnum.SomeTypeId,
CreatedBy=400,
CreationTimeUtc"=new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc)
};
var newId=con.ExecuteScalar(sql,theParams);
</code>
<code>var theParams=new { MyTypeId=DataTypeEnum.SomeTypeId, CreatedBy=400, CreationTimeUtc"=new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc) }; var newId=con.ExecuteScalar(sql,theParams); </code>
var theParams=new {
    MyTypeId=DataTypeEnum.SomeTypeId,
    CreatedBy=400,
    CreationTimeUtc"=new DateTime(2018, 1, 1, 12, 0, 0,DateTimeKind.Utc)
};

var newId=con.ExecuteScalar(sql,theParams);

Batching

It seems the actual question is how to batch multiple queries. This is shown in the Batching section of the Basic Usage docs. There are two ways to do this.

The legacy way is to create a single string, separating the queries by a semicolon. This isn’t supported by PostgreSQL itself though. NpgSql has to parse the query, find the semicolons and split the string into individual statements :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>var sql="""
INSERT INTO table (col1) VALUES ('foo');
SELECT * FROM table
""";
await using var cmd = new NpgsqlCommand(sql, conn);
await using var reader = await cmd.ExecuteReaderAsync();
</code>
<code>var sql=""" INSERT INTO table (col1) VALUES ('foo'); SELECT * FROM table """; await using var cmd = new NpgsqlCommand(sql, conn); await using var reader = await cmd.ExecuteReaderAsync(); </code>
var sql="""
        INSERT INTO table (col1) VALUES ('foo'); 
        SELECT * FROM table
        """;
await using var cmd = new NpgsqlCommand(sql, conn);
await using var reader = await cmd.ExecuteReaderAsync();

The current way is to use a NpgSqlBatch instance containing the individual commands:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>await using var batch = new NpgsqlBatch(conn)
{
BatchCommands =
{
new("INSERT INTO table (col1) VALUES ('foo')"),
new("SELECT * FROM table")
}
};
await using var reader = await batch.ExecuteReaderAsync();
</code>
<code>await using var batch = new NpgsqlBatch(conn) { BatchCommands = { new("INSERT INTO table (col1) VALUES ('foo')"), new("SELECT * FROM table") } }; await using var reader = await batch.ExecuteReaderAsync(); </code>
await using var batch = new NpgsqlBatch(conn)
{
    BatchCommands =
    {
        new("INSERT INTO table (col1) VALUES ('foo')"),
        new("SELECT * FROM table")
    }
};

await using var reader = await batch.ExecuteReaderAsync();

Inserting the generated ID from the first INSERT into another table isn’t as simple as using currval in the second INSERT though. Sequences aren’t affected by transactions so currval will return the current sequence value, not the last value created in the same batch or transaction. If 2 or more connections execute INSERT at the same time, they may both end up using the same ID value.

In this particular case it’s possible to use a single statement, by using INSERT .. RETURNING as a normal query, in a CTE or subquery :

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>with times as (
INSERT INTO public.production_items (
my_data_type_id,
created_by,
creation_time_utc)
VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
RETURNING Id
)
INSERT INTO public.some_other_table (
some_other_table_id,
some_additional_table)
SELECT
times.Id,
@SomeAdditionalTableValue
from times;
</code>
<code>with times as ( INSERT INTO public.production_items ( my_data_type_id, created_by, creation_time_utc) VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc) RETURNING Id ) INSERT INTO public.some_other_table ( some_other_table_id, some_additional_table) SELECT times.Id, @SomeAdditionalTableValue from times; </code>
with times as (
    INSERT INTO public.production_items (
        my_data_type_id, 
        created_by, 
        creation_time_utc)
    VALUES (@MyTypeId, @CreatedBy, @CreationTimeUtc)
    RETURNING Id
)
INSERT INTO public.some_other_table (
    some_other_table_id, 
    some_additional_table)
SELECT 
    times.Id, 
    @SomeAdditionalTableValue
from times;

5

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật