Cross-posted from “What would be the best way to store the country of a user in SQL?” by @[email protected] in [email protected]


I use Gorm. This is the current code:

package main

import (
	"fmt"
	"log"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type Env struct {
	DB     *gorm.DB
	Logger *log.Logger
}

type User struct {
	ID           uint
	Username     string
	Name         string
	Email        string
	PasswordHash string
	Country      string //should probably be a foreign key of another table
}

func initDB() {
	env := &Env{}
	db, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{})
	if err != nil {
		fmt.Printf("Error opening database: %v", err)
		return
	}
	env.DB = db
	env.DB.AutoMigrate(&User{})

}

func main() {
	initDB()
}

As you can see in the comment in the code, I assume the best way would be to have a table of countries and then assign each user to one via a foreign key. However, it seems a bit cumbersome to manually create a list of all countries. Is there a better way to do this?

    • @[email protected]
      link
      fedilink
      825 days ago

      Same for using an “almost non-changing” standard, i.e. either ISO or RFC. And write a script to update the data or tables if something wrong changes (like Russia disappearing because it has been invaded by Belgium), you never know what might happen politically.

    • @[email protected]
      link
      fedilink
      2725 days ago

      This and nothing else. Had to deal with way too many APIs that would use some sort of homebrew schema.

    • LenaOP
      link
      fedilink
      English
      625 days ago

      Am I supposed to make an SQL statement that puts these country codes into a table, along with the country’s name? There’s probably a better way. Maybe I could make a new entry for every unique country a user is from

      • @[email protected]
        link
        fedilink
        2925 days ago

        Why do you need to store the name of a country in the database? Frontend can take the country code and display a full name on its own, and do it in a localized way too.

      • JackbyDev
        link
        fedilink
        English
        123 days ago

        You don’t need these in a table the same way you don’t need a table for something like true and false. Two characters is enough to deduce all the information.

      • @[email protected]
        link
        fedilink
        825 days ago

        not sure I understand the distinction between the “am I supposed to” and “maybe I could” parts?

        You should create a table of all countries, you can just copy that from the above link. Then you reference that table with a foreign key in your users table.

        • LenaOP
          link
          fedilink
          English
          025 days ago

          Sooooo I copy paste every single country code and put it in a table?

          • @[email protected]
            link
            fedilink
            425 days ago

            How exactly you create that table is up to you of course, I don’t know enough about your project setup.

          • @[email protected]
            link
            fedilink
            English
            224 days ago

            If you can’t figure out how to get a foreign table into your database let someone who knows databases do it for you

          • @[email protected]
            link
            fedilink
            323 days ago

            That’s a perfectly valid approach, yes. We do exactly this, at work. It’s pretty common, if not ubiquitous, to have your database schema consist of not only structure, but data as well. We call it static data, and it’s all defined in deployable scripts, just like our tables and views are. If ISO makes changes to the dataset, then it’s just a table update to match it. And ISO is nice about keeping backwards compatibility inb their standards.

            Since this is not strictly your own data, you could also go with just storing the code value on your tables, and letting the UI layer do the lookup, either with built-in features of your language/framework, or with a static csv file, like you mention. You may not want to do this for static data that is entirely your own, like, say, a status or type enum, since it makes your database schema less-self-descriptive, and more prone to becoming invalid.

            You could also set the country code up as a not-strictly-enforced foreign key, where your app will lookup additional info (E.G. the proper name) for a country code, if it’s a standard one, but just skip that if it’s not a standard one.

            It’s up to you what you think is most appropriate.

  • Rikudou_Sage
    link
    fedilink
    325 days ago

    I’d store it as a string (ISO code), pretty much every programming language has icu data for country names.

    If you need more data later, it’s very simple to migrate.

  • @[email protected]
    link
    fedilink
    English
    224 days ago

    I’m a fan of CountryCode being a string column that’s a FK to a reference table of Country values.

    Same for State/Province.

  • @[email protected]
    link
    fedilink
    English
    1
    edit-2
    24 days ago

    It will depend upon other things you might want to do with it in the future.
    If you want the record to stay “correct” in the future, you might want to have a separate entry for nationality information, which will be a 1-to-1 mapping with the other table you make for it. Why? …

    • in the nationality information, along with the country code (for which you want to allow 3 character codes for forward compatibility), the date at which the the information was given in the form
    • if possible, also include the date at which the nationality was provided (as in, provided to the user by the nation)

    This should help determine what kind of change may occur in case of changes in the political landscape in the future, without you requiring to re-ask the form-filler.


    Inspired by https://flightaware.engineering/falsehoods-programmers-believe-about-aviation/
    And I am going to consider this stuff every time I make a database schema.

    Stuff in the real world is subject to change, so instead of only storing the provided data as you asked for, make a ledger for events. And someone submitting a forms, will be another event.

    This way, you get the flexibility to verify the provided data in the future, using information that you will have in the future, but don’t have at the time the data was provided.

    Of course, this is only needed if it is needed.

  • @[email protected]
    link
    fedilink
    425 days ago

    GPS coordinates. Much more efficient than storing country, province, city, address, and postal code. Let the front end handle the rest.

    • @[email protected]
      link
      fedilink
      525 days ago

      Terrible idea for a few reasons.

      • The example in the OP does not need anything but the country. GPS coordinates are less efficient than ISO codes
      • GPS coordinates don’t map 1:1 to countries or even street addresses. There are infinite different coordinates for each address, and it’s very non-trivial to match one to another. Comparing whether two records with country codes are in the same country is trivial. Doing the same with two GPS coordinates is very difficult.
      • GPS coordinates might be more exact than accurate. This is a surprisingly common issue: you start out only needing a country, so you put some arvitrary GPS position (e.g. the center of the country) into the GPS coordinates. Later a new requirement arises that means you now need street addresses. Now all old entries point so some random house in the middle of the country, and there’s no easy way to differentiate these false locations from real ones.
    • Björn Tantau
      link
      fedilink
      725 days ago

      GPS? Absolutely insufficient. What about the people on the ISS? Or when the moon base is established? Ever thought of that? No. You think only of yourself.

      • @[email protected]
        link
        fedilink
        124 days ago

        Simple, add additional columns for the frame of reference (e.g. Earth) and elevation. You could even store space coordinates using Sun as a reference point (though you would need to update data regularly for spacecraft as they move of course).

        • TehPers
          link
          fedilink
          English
          425 days ago

          You should also include the standardized name of the body the coordinates are relative to. Need to be able to differentiate between lat/long on Jupiter vs on Earth (where lat/long are much more “crunched” aka more precise with shorter floats).

          This will be important if intelligent extraterrestrial life is found, or when Musk ships himself to Mars for the good of humanity.

      • @[email protected]
        link
        fedilink
        English
        124 days ago

        GPS: Galactic Positioning System

        Just suppose you are not selling the software outside of the galaxy and you will have to update your database (and transform and migrate all the data) when the 2 galaxy positioning system is formed.

        • Björn Tantau
          link
          fedilink
          2
          edit-2
          24 days ago

          Ugh, this will be chaos when we crash into Andromeda. I’m not looking forward to the next billions of years.

          • @[email protected]
            link
            fedilink
            English
            124 days ago

            Just complete your KRAs beforehand and hand over the project to the Junior Dev, before then.