{"id":95014,"date":"2022-11-05T03:09:33","date_gmt":"2022-11-05T03:09:33","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=95014"},"modified":"2022-11-09T09:29:45","modified_gmt":"2022-11-09T09:29:45","slug":"how-to-use-any-sql-database-in-go-with-gorm","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/development\/other-development\/how-to-use-any-sql-database-in-go-with-gorm\/","title":{"rendered":"GORM Tutorial: Using the Go ORM with MySQL, PostgreSQL, SQLite, and SQL Server &#8211; Connections, Models, Automigrations, and CRUD"},"content":{"rendered":"<p><b>GORM is the most widely-used Object-Relational Mapping (ORM) library for the Go programming language &#8211; a code-first, database-agnostic ORM that lets Go applications interact with MySQL, PostgreSQL, SQLite, SQL Server, ClickHouse, and other relational databases through the same API. Core concept: define your data models as Go structs with tags, and GORM handles the schema creation (via automigrations), the SQL generation (CRUD operations via typed methods), and the result mapping (query results unmarshalled back into structs). This article walks through GORM end-to-end: (1) installation and setup &#8211; importing the GORM package and the appropriate database driver; (2) connecting to different database engines &#8211; the connection-string pattern differs per database but the GORM API surface is identical; (3) defining models as Go structs with GORM tags for column names, types, and constraints; (4) automigrations &#8211; having GORM create or update the database schema to match your struct definitions; (5) CRUD operations &#8211; Create for inserts, First\/Find\/Where for queries, Save\/Updates for updates, Delete for deletes; (6) the GORM SQL builder for cases where the ORM abstraction gets in the way and you need direct SQL control. GORM is the pragmatic choice for Go applications where ORM productivity outweighs the modest performance overhead; for performance-critical paths, the SQL builder or the standard database\/sql package remain available.<\/b><\/p>\n<p>Object Relational Mapping is a database abstraction technique that aids developers in manipulating and interacting with SQL databases using the data types provided in the programming language.<\/p>\n<p>ORMs (Object Relational Mappers) are tools (libraries, modules, packages) that provide the functionality for interacting with SQL databases. Popular ORMs are the Prisma ORM for JavaScript, TypeScript, Hibernate for Java, and SQLAlchemy for Python.<\/p>\n<p>Aside from the benefit of interacting with SQL databases in a more natural manner than writing raw SQL, there are many other benefits of using ORMs. Without worrying too much about compatibility, you can use any databases supported by an ORM with the same code (when using common functionality, not every feature will be available for every database type.)<\/p>\n<p><a href=\"http:\/\/gorm.io\">GORM <\/a>is the most popular ORM in the Go ecosystem. GORM (Go-ORM) is a developer-friendly, full-featured, Code-first ORM for interacting with SQL databases in Go. GORM provides drivers and functionalities like associations, automigration, SQL building, logging, and hooks for database operations, and support for popular SQL databases including MySQL, SQLite, PostgreSQL, Microsoft SQL server, and many database drivers.<\/p>\n<h2>Getting Started with GORM<\/h2>\n<p>You\u2019ll need to meet a few requirements to get the most out of this article.<\/p>\n<ul>\n<li>You have <a href=\"http:\/\/gobyexample.com\">experience working with Go<\/a> and have Go installed on your machine.<\/li>\n<li>You have experience working with SQL and SQL databases.<\/li>\n<\/ul>\n<p>In this tutorial, you\u2019ll learn how to use GORM with an SQLite database. The processes are generally the same for all other supported SQL databases.<\/p>\n<p>After creating a Go workspace, Install the GORM package using these commands in your working directory.<\/p>\n<pre class=\"lang:none theme:none\">      go get gorm.io\/gorm<\/pre>\n<p>You\u2019ll need a database driver to work with GORM. Fortunately, GORM also provides database drivers for the popular SQL databases. Install the database driver for your preferred database using any of these commands.<\/p>\n<pre class=\"lang:none theme:none\">go get gorm.io\/driver\/sqlite \/\/SQLite \r\ngo get gorm.io\/driver\/mysql \/\/ MySQL \r\ngo get gorm.io\/driver\/postgres \/\/PostgreSQL \r\ngo get gorm.io\/driver\/sqlserver \/\/MSSQL \r\ngo get gorm.io\/driver\/clickhouse \/\/click house <\/pre>\n<p>GORM also provides functionalities for using custom database drivers. This is beyond the scope of this article, but you can read more <a href=\"https:\/\/gorm.io\/docs\/write_driver.html\">here<\/a>.<\/p>\n<p>After installing your database driver, you can import the driver for use.<\/p>\n<pre class=\"lang:none theme:none\">      import ( \r\n        \"gorm.io\/gorm\" \r\n        _ \"github.com\/mattn\/go-sqlite3\" \r\n      )<\/pre>\n<p>As shown above, you\u2019ll have to import the database driver for side effects. (This allows interactions with the database over GORMs interface to do things like query and modify data.)<\/p>\n<h2>Connecting to Databases using GORM<\/h2>\n<p>After installing and importing the GORM package and your preferred database driver, you can proceed to connect to your database.<\/p>\n<p>Use the Open method of the gorm module to connect to a database. The Open method takes in the connection and configuration methods as input and returns the database connection instance.<\/p>\n<pre class=\"lang:none theme:none\">db, err = gorm.Open(sqlite.Open(\"Blogs.db\"), &amp;gorm.Config{})\r\n \r\nif err != nil { \r\n     panic(\"failed to connect database\") \r\n}<\/pre>\n<p>The previous code connects to an in-memory SQLite database in the code example above. For SQLite, the <code>Open<\/code> method creates a database in your working directory if the database doesn\u2019t exist. The process is similar if you connect to a database with a connection string. In the following code, I am connecting to a MySQL database using a connection string.<\/p>\n<pre class=\"lang:none theme:none\">Db, err =        gorm.Open(mysql.Open(\u201croot:admin@tcp(127.0.0.1:3306)\/yourdatabase?charset=utf8mb4&amp;parseTime=True&amp;loc=Local\u201d), &amp;gorm.Config{}) \r\nif err != nil { \r\n   panic(\u201cfailed to connect database\u201d) \r\n}<\/pre>\n<p>Connecting to a database is similar if you use a custom database driver. You must connect to the database based on the specifications that were included in the driver, and pass the connection details to the <code>Open<\/code> method.<\/p>\n<pre class=\"lang:none theme:none\">Db, err := gorm.Open(\u201csqlite3\u201d, \u201c.\/app.db\u201d)<\/pre>\n<p>In this case, you\u2019re using the custom SQLite driver imported above. On a successful database connection, you\u2019ll be able to interact with the database with Go data types in the same way.<\/p>\n<h2>Mapping Go Types With GORM<\/h2>\n<p>GORM is a code-first ORM. This means you won\u2019t have to define your schema in SQL. For GORM, you use Go structs to describe the schema and column types with GORM tags.<\/p>\n<pre class=\"lang:none theme:none\">Type Human struct { \r\n   Age int \r\n   Name string \r\n}<\/pre>\n<p>On migration, the <code>Human<\/code> struct will be translated to the database schema. The table&#8217;s name in the database will be <code>Human<\/code> and the <code>Age<\/code> and <code>Name<\/code> fields are the column names.<\/p>\n<p>GORM provides tags for adding SQL constraints like primary key, foreign keys, index, not null and other database constraints. Here\u2019s how you can add a GORM tag to a struct.<\/p>\n<pre class=\"lang:none theme:none\">type Human struct { \r\n    Age int `gorm:\"primaryKey\"` \r\n    Name string `gorm:\"size:255;not null;unique\"` \r\n}<\/pre>\n<p>The Age field has a primary key constraint, and the Name field has size, not null and unique constraints.<\/p>\n<p>For easy schema modelling, GORM provides the GORM Model. The GORM model is a struct that contains popularly used fields like <code>ID<\/code> as the primary key and the created, updated, and deleted time as columns. You can use the <code>Model<\/code> struct by passing the model to your struct.<\/p>\n<pre class=\"lang:none theme:none\">type Human struct { \r\n   gorm.Model \r\n   Age int `gorm:\"primaryKey\"` \r\n   Name string `gorm:\"size:255;not null;unique\"` \r\n}<\/pre>\n<p>The Human struct above evaluates to the HumanPlus struct below in the database on migration since <a href=\"https:\/\/www.makeuseof.com\/how-to-implement-object-oriented-programming-concepts-in-go\/\">the Human struct inherits the gorm.Model struct<\/a>.<\/p>\n<pre class=\"lang:none theme:none\">type HumanPlus struct { \r\n   Age int `gorm:\"primaryKey\"` \r\n   Name string `gorm:\"size:255;not null;unique\"` \r\n   ID uint `gorm:\"primaryKey\"` \r\n   CreatedAt time.Time \r\n   UpdatedAt time.Time \r\n   DeletedAt gorm.DeletedAt `gorm:\"index\"` \r\n}<\/pre>\n<p>You can embed your custom structs in other structs using the embedded tag.<\/p>\n<pre class=\"lang:none theme:none\">type Human struct { \r\n   Age int `gorm:\"primaryKey\"` \r\n   Name string `gorm:\"size:255;not null;unique\"` \r\n} \r\ntype Beings struct { \r\n   human Human `gorm:\"embedded\"` \r\n   gorm.Model \r\n}<\/pre>\n<p>The <code>Beings<\/code> struct eventually evaluates to the <code>Evaluate<\/code> struct below on migration.<\/p>\n<pre class=\"lang:none theme:none\">type Evaluate struct { \r\n   Age int `gorm:\"primaryKey\"` \r\n   Name string `gorm:\"size:255;not null;unique\"` \r\n   ID uint `gorm:\"primaryKey\"` \r\n   CreatedAt time.Time \r\n   UpdatedAt time.Time \r\n   DeletedAt gorm.DeletedAt `gorm:\"index\"` \r\n}<\/pre>\n<p>GORM supports most features you\u2019ll want in an ORM, including functionality to set field permissions for more data control. Here\u2019s the complete reference from the <a href=\"https:\/\/gorm.io\/docs\/models.html#:~:text=to%20create%20table-,type,-User%20struct%20%7B\">GORM documentation<\/a>.<\/p>\n<pre class=\"lang:none theme:none\">type User struct { \r\n   Name string `gorm:\"&lt;-:create\"` \/\/ allow read and create \r\n   Name string `gorm:\"&lt;-:update\"` \/\/ allow read and update \r\n   Name string `gorm:\"&lt;-\"` \/\/ allow read and write (create and update) \r\n   Name string `gorm:\"&lt;-:false\"` \/\/ allow read, disable write permission \r\n   Name string `gorm:\"-&gt;\"` \/\/ readonly (disable write permission \r\n                           \/\/unless it       configured) \r\n   Name string `gorm:\"-&gt;;&lt;-:create\"` \/\/ allow read and create \r\n   Name string `gorm:\"-&gt;:false;&lt;-:create\"` \/\/ create only (disabled read \r\n                                                          \/\/from db) \r\n   Name string `gorm:\"-\"` \/\/ ignore this field when writing and \r\n                          \/\/reading with struct \r\n   Name string `gorm:\"-:all\"` \/\/ ignore this field when writing, \r\n                              \/\/reading and migrating with struct \r\n   Name string `gorm:\"-:migration\"` \/\/ ignore this field when migrate \r\n                                    \/\/with struct \r\n}<\/pre>\n<h2>Setting up Automigrations With GORM<\/h2>\n<p>Automigrations are one of the significant benefits of using ORMs, making it easy to add data entries. You can migrate instances of the struct model using the <code>AutoMigrate<\/code> method of the database instance.<\/p>\n<pre class=\"lang:none theme:none\">err = db.AutoMigrate(&amp;Human{}) \r\nif err != nil { \r\n    panic(\"migration failure\") \r\n}<\/pre>\n<p>By referencing the struct here, you\u2019ve set the Human struct for auto migration. The <code>AutoMigrate<\/code> method returns an error that you can handle if any.<\/p>\n<p>Conventionally, you\u2019ll use the function that returns your database instance to set up auto migrations and return the database instance.<\/p>\n<pre class=\"lang:none theme:none\">func database(DNS string) *gorm.DB { \r\n   var db *gorm.DB \r\n   db, err = gorm.Open(mysql.Open(DNS), &amp;gorm.Config{}) \r\n   if err != nil { \r\n      panic(\"failed to connect database\") \r\n   } \r\n   err = db.AutoMigrate(&amp;Human{}) \r\n   if err != nil { \r\n      return \r\n   } \r\n      return db \r\n   }<\/pre>\n<h2>Inserting Into a Database With GORM<\/h2>\n<p>The Create method accepts a reference to the struct initialization and inserts a new row to the database.<\/p>\n<pre class=\"lang:none theme:none\">person := Human{ \r\n   Model: gorm.Model{}, \r\n   Age: 18, \r\n   Name: \"James Dough\", \r\n} \r\ndb.Create(&amp;person)<\/pre>\n<p>Depending on your operation; you can use many methods and functions on the Create method.<\/p>\n<p>Using the RowsAffected method on the Create method returns the number of Rows affected.<\/p>\n<pre class=\"lang:none theme:none\">rows := db.Create(&amp;person).RowsAffected \r\nlog.Println(rows) <\/pre>\n<p>There are many other methods you can use with the <code>Create<\/code> method. In figure1 you can see a few of them.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-95015\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/11\/graphical-user-interface-text-description-automa-1.png\" alt=\"Graphical user interface, text\n\nDescription automatically generated with medium confidence\" width=\"1025\" height=\"446\" \/><\/p>\n<p class=\"caption\">Figure 1 &#8211; Additional methods you can use with the Create method.<\/p>\n<h2>Reading From a Database With GORM<\/h2>\n<p>Reading from a database with GORM is easy, and there are many methods you can use based on the operation.<\/p>\n<p>The read methods decode the query result into an instantiated struct.<\/p>\n<pre class=\"lang:none theme:none\">      type person := new(Human)<\/pre>\n<p>The <code>Take<\/code> , <code>First<\/code> , and <code>Last<\/code> methods return a single row. The <code>Take<\/code> method returns a random row that meets the criteria; the <code>First<\/code> method returns the first entry that satisfies the query ordered primary key, and the <code>Last<\/code> method returns the last entry that satisfies the query ordered primary key.<\/p>\n<pre class=\"lang:none theme:none\">db.Take(&amp;person, \"John\") \r\ndb.First(&amp;person, \"Jane\") \r\ndb.Last(&amp;person, \"Dough\")<\/pre>\n<p>Using the <code>Find<\/code> method, you can also query for all the rows that meet the criteria.<\/p>\n<pre class=\"lang:none theme:none\">      db.Find(&amp;person, \"James\")<\/pre>\n<p>You can use the Where method with any of the <code>Find<\/code> , <code>First<\/code> , <code>Take<\/code> and <code>Last<\/code> methods for complex queries.<\/p>\n<pre class=\"lang:none theme:none\">     db.Where(\"Name = ? AND Age &gt;= ?\", \"James\", \"22\").Find(&amp;person)<\/pre>\n<h2>Updating Database Entries With GORM<\/h2>\n<p>Update operations are easy and quite similar to other GORM operations, and all the methods and functions on read operations are also available.<\/p>\n<p>You can update a column using the <code>Update<\/code> method after referencing the struct table you want to update using the <code>Model<\/code> method.<\/p>\n<pre class=\"lang:none theme:none\">     var rows = db.Model(&amp;Human{}).Update(\"Name\", \"Junior\").RowsAffected<\/pre>\n<p>After a successful update operation, the rows variable will store the number of rows affected by the operation.<\/p>\n<p>You can also update multiple columns using the <code>Updates<\/code> method. The <code>Updates<\/code> method takes in an initialized struct.<\/p>\n<pre class=\"lang:none theme:none\">person := Human{ \r\n    Name: \"James\", \r\n    Age: 18, \r\n} \r\ndb.Model(&amp;person).Updates(person)<\/pre>\n<p>Like the read operation, you can use the Where method with any update methods for complex operations.<\/p>\n<pre class=\"lang:none theme:none\">    db.Model(&amp;Human{}).Where(\"Age = ?\", 19).Update(\"Name\", \"Junior\")<\/pre>\n<h2>Deleting From a Database With GORM<\/h2>\n<p>You can use the Delete method to delete rows in a database. The <code>Delete<\/code> method takes in the instantiated struct type.<\/p>\n<pre class=\"lang:none theme:none\">      db.Delete(&amp;person)<\/pre>\n<p>You can also use the Delete method on the Where method for complex operations<\/p>\n<pre class=\"lang:none theme:none\">      db.Where(\"name = ?\", \"John\").Delete(&amp;person)<\/pre>\n<p>If you need to delete specific columns, You can drop a column using the <code>DropColumn<\/code> method of the Migrator method of the database instance.<\/p>\n<pre class=\"lang:none theme:none\">err := db.Migrator().DropColumn(&amp;Human{}, \"Name\") \r\nif err != nil { \r\nreturn \r\n}<\/pre>\n<p>Here you dropped the Name column of the Human table. The <code>DropColumn<\/code> method returns an error if there\u2019s any.<\/p>\n<h2>The GORM SQL Builder<\/h2>\n<p><a href=\"https:\/\/stackoverflow.com\/questions\/4667906\/the-advantages-and-disadvantages-of-using-orm\">One of the cons<\/a> of using ORMs, in general, is the abstraction ORMs provide over the database, reducing the power and flexibility of interacting with databases. Most ORMs like GORM provide SQL builders for raw SQL queries and operations.<\/p>\n<p>You can use the Raw method to write raw SQL queries. The methods on the Raw method serve various functionalities. The Scan method returns the result of the query into the instantiated struct.<\/p>\n<pre class=\"lang:none theme:none\">type Result struct { \r\n   ID int \r\n   Name string \r\n   Age int \r\n}\r\n \r\nvar output Result \r\ndb.Raw(\"SELECT id, Name, Age FROM Human WHERE Name = ?\", \"James\").Scan(&amp;output)<\/pre>\n<p>In this case, GORM would decode the output of the SQL query into the <code>output<\/code> variable You can also execute SQL statements using the Exec method of your database instance.<\/p>\n<pre class=\"lang:none theme:none\">db.Exec(\"DROP TABLE Human\")<\/pre>\n<h2>Conclusion<\/h2>\n<p>GORM provides most of the functionalities you\u2019ll need in an ORM while prioritizing efficiency and security, making the library every Go developer\u2019s choice for interacting with SQL databases.<\/p>\n<p>In this tutorial, you learned about the GORM library to increase productivity while interacting with databases with Go. You can perform many more operations with the GORM library, and this article has given you an overview. You can check out <a href=\"https:\/\/gorm.io\/\">GORM\u2019s documentation<\/a> to learn more about the library.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A complete GORM tutorial covering how to use the Go ORM with any SQL database: connecting to MySQL, PostgreSQL, SQLite, or SQL Server; defining Go struct models with tags; automigrations; CRUD operations (Create, First, Find, Where, Updates, Delete); and dropping to raw SQL via the GORM SQL builder when needed.&hellip;<\/p>\n","protected":false},"author":340771,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,147591],"tags":[],"coauthors":[147592],"class_list":["post-95014","post","type-post","status-publish","format-standard","hentry","category-featured","category-other-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/95014","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/340771"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=95014"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/95014\/revisions"}],"predecessor-version":[{"id":95017,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/95014\/revisions\/95017"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=95014"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=95014"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=95014"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=95014"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}