PostgreSQL Parameterized Insert with ADO.NET

12,068

The responses in the comments are correct:

  1. Npgsql doesn't support _ as a parameter placeholder notation. You should be using @ or : (so @FirstName or :FirstName, not _FirstName).
  2. PostgreSQL will automatically lower-case your table and column names unless they are double-quoted. Either use lower-case names for everything (simpler) or quote identifiers in your SQL queries.

So your code should look more or less like this:

IDbCommand command = conn.CreateCommand();
string sql = "INSERT INTO Customers (first_name, last_name) VALUES (@FirstName,@LastName)";
command.CommandText = sql;

var parameter = command.CreateParameter();
parameter.ParameterName = "FirstName";
parameter.Value = "Test";
command.Parameters.Add(parameter);
Share:
12,068
Greg Finzer
Author by

Greg Finzer

I am the owner of Kellerman Software. I have several open source and commercial products. Visit http://www.kellermansoftware.com Free Quick Reference Pack for Developers Free Sharp Zip Wrapper NUnit Test Generator (also generates xUnit and MS Test stubs) .NET Caching Library .NET Email Validation Library .NET FTP Library .NET Encryption Library .NET Logging Library Themed Winform Wizard Unused Stored Procedures AccessDiff (Compare Access object and data differences) .NET SFTP Library Ninja Database Pro (Object database for .NET, Silverlight, Windows Phone 7) Ninja WinRT Database (Object database for Windows Runtime) Knight Data Access Layer (ORM, LINQ Provider, Generator for SQL Server, Oracle, MySQL, Firebird, MS Access, VistaDB) Here is my open source project: https://github.com/GregFinzer/Compare-Net-Objects

Updated on June 06, 2022

Comments

  • Greg Finzer
    Greg Finzer almost 2 years

    I am using NpgSQL with PostgreSQL and ADO.NET. Forgive the simplicity of the question as I just started using PostgreSQL and NpgSQL this week.

    Something like this works fine:

    [Test]
    public void InsertNoParameters()
    {
        NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
        conn.Open();
    
        IDbCommand command = conn.CreateCommand();
        string sql = "INSERT INTO Customers (FirstName,LastName) VALUES ('Test','Tube')";
        command.CommandText = sql;
        command.ExecuteNonQuery();
        conn.Close();
    }
    

    When I put in parameters I get the error message: Npgsql.NpgsqlException : ERROR: 42703: column "_firstname" does not exist

    [Test]
    public void InsertWithParameters()
    {
    NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
    conn.Open();
    
    IDbCommand command = conn.CreateCommand();
    string sql = "INSERT INTO Customers (FirstName,LastName) VALUES (_FirstName,_LastName)";
    command.CommandText = sql;
    
    var parameter = command.CreateParameter();
    parameter.ParameterName = "_FirstName";
    parameter.Value = "Test";
    command.Parameters.Add(parameter);
    
    parameter = command.CreateParameter();
    parameter.ParameterName = "_LastName";
    parameter.Value = "Tube";
    command.Parameters.Add(parameter);
    
    command.ExecuteNonQuery();
    conn.Close();
    }
    
    • wildplasser
      wildplasser over 8 years
      Uppercase <> lowercase. Either use lowercase only or quote your identifiers (using double quotes).
    • Greg Finzer
      Greg Finzer over 8 years
      I just tried all lower case parameter names and I am still getting the same error.
    • wildplasser
      wildplasser over 8 years
      in psql (or pgadmin) inspect what the actual names of your columns are.
    • Mark Rotteveel
      Mark Rotteveel over 8 years
      As far as I know, most drivers including the postgresql driver follow the microsoft convention to identify parameters with an @ prefix, not an underscore (_)
    • Greg Finzer
      Greg Finzer over 8 years
      It looks like it has to be an @ sign. It is strange because the @ is invalid for function parameters.
    • Mark Rotteveel
      Mark Rotteveel over 8 years
      @Greg''Wildman''Finzer That's irrelevant, it is handled in the driver, not in the server.
  • Kasey Speakman
    Kasey Speakman over 7 years
    I disagree with #2 recommendations. Quoted identifiers should not be used generally. If you define a field with quotes you also have to use them every time you reference that field. So it better be worth it (but it won't be). Casing vs underscore is debatable. Using cased names does work just fine without quoted identifiers, and it will be preferable sometimes... depends on the project.
  • Shay Rojansky
    Shay Rojansky over 7 years
    Using cased names does not work just fine without quoted identifiers, in the sense that PostgreSQL will fold the name to lowercase. This means that Ident1 and ident1 will be in conflict. There's nothing particularly wrong with quoting your identifiers - this is a standard PostgreSQL practice and a necessity where mixed case is desired. For example, an O/RM which maps C# property names to database columns (e.g. Entity Framework) will typically quote all identifiers.
  • Kasey Speakman
    Kasey Speakman over 7 years
    You can issue definition queries and data queries with cased names, and it will work just fine. Postgres will handle them with it's version of "case insensitivity", meaning they will be lower cased. ORMs not able to map a lower-cased names to a case-named object properties will probably also have problem with your other suggestion of using underscores. ORMs that create columns with quoted identifiers are creating a debt that it's users will have to pay in the future.
  • Shay Rojansky
    Shay Rojansky over 7 years
    Everything will work "just fine", until you happen to have two identifiers that are identical if folded to lowercase. This is why any O/RM that maps identifier from a case-sensitive language (such as C#) to PostgreSQL absolutely must quote, otherwise sooner or later two properties will fold into the same lowercase and boom.
  • Shay Rojansky
    Shay Rojansky over 7 years
    If you control all applications accessing your database and can make sure all identifiers are distinct, it's fine not to quote. If you're writing a general-purpose component such as an O/RM there's a very good chance you must quote. It all depends on the context.