76

Given an OO language in which the naming convention for object properties is camelCased, and an example object like this:

{
    id: 667,
    firstName: "Vladimir",
    lastName: "Horowitz",
    canPlayPiano: true
}

How should I model this structure in a PostgreSQL table? Options:

  1. unquoted camelCase column names
  2. quoted camelCase column names
  3. unquoted (lowercase) names with underscores

Each have drawbacks:

  1. Unquoted identifiers fold to lowercase. You can create a table with a canPlayPiano column, but the mixed case never reaches the database. The column will show up as canplaypiano in psql, pgAdmin, explain results, error messages, everwhere.

  2. Quoted identifiers keep their case, but once you create them like that you will always have to quote them. If you create a table with a "canPlayPiano" column, a SELECT canPlayPiano ... will fail. This adds noise to all SQL statements.

  3. Lowercase names with underscores are unambiguous but they don't map to the names the application language is using. You will have to remember to use different names for storage (can_play_piano) and code (canPlayPiano). It also prevents certain types of code automation where properties and database columns need to be named the same.

Whatever I do, some part is going to feel awkward. I've been using option 3, but keep hoping for a better solution. The case folding and the need for quotes is coming from the SQL standard (PostgreSQL's adaptation of the standard). I know how it works; I'm more interested in best practices than explanations about how PostgreSQL handles identifiers.

user4157124
  • 2,809
  • 13
  • 27
  • 42
Zilk
  • 8,917
  • 7
  • 36
  • 44
  • Even if you go with all lower-case, I recommend that you have your database abstraction layer always wrap all identifiers with quotes in the generated queries. You can't always predict what new keywords will be used in a new release, so you gain protection from conflicting names by quoting. – kgrittn Jun 30 '12 at 16:31

3 Answers3

51

If your columns in the PostgreSQL are with underscores, you can put aliases but with doule-quotes.

Example :

SELECT my_column as "myColumn" from table;
Mirza Selimovic
  • 1,669
  • 15
  • 18
32

Given that PostgreSQL uses case-insensitive identifiers with underscores, should you change all your identifiers in your application to do the same? Clearly not. So why do you think the reverse is a reasonable choice?

The convention in PostgreSQL has come about through a mix of standards compliance and long-term experience of its users. Stick with it.

If translating between column-names and identifiers gets tedious, have the computer do it - they're good at things like that. I'm guessing almost all of the 9-million database abstraction libraries out there can do that. If you have a dynamic language it'll take you all of two lines of code to swap column-names to identifiers in CamelCase.

Richard Huxton
  • 21,516
  • 3
  • 39
  • 51
  • 5
    There might be many cases where this is acceptable but it comes at a performance cost. I recently spent hours debugging query performance finding out that more than 50% of the response time was spent with renaming columns. Granted it was a large dataset but nothing crazy for today's times.I'd wish this answer would highlight that little trap – kraf Oct 18 '19 at 12:01
  • 1
    Per this answer, use the conventions common to the domain. Since SQL is case-insensitive, and sometablename is harder to read than some_table_name, the common convention is snake case. This actually can make it easier for ORMs to give you friendly upper layer names because it is trivial to strip underscores and capitalize the letter after the underscore. Otherwise, you are pretty much looking at defining the mapping youself. – Chris Golledge Jun 16 '20 at 20:33
1

I know this is late however for something that would be simple to translate on the fly, you could write a small help function that would live in your code as such:

function FormatObjForDb(srcObj){
    const newObj = {};
    Object.keys(srcObj).forEach(key => newObj[key.toLowerCase()] = srcObj[key]);
    return newObj;
}

export const formatObjForDb = FormatObjForDb;
Akaisteph7
  • 5,034
  • 2
  • 20
  • 43
  • I'm not sure why you redefine your function with a different case. It also only converts to lower case, but I think going from lowercase or snake_case to camelCase will be what is required. And an example usage to auto apply to all returned columns would be more helpful. – Akaisteph7 Aug 09 '23 at 15:44