{"id":93475,"date":"2022-03-01T17:20:56","date_gmt":"2022-03-01T17:20:56","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=93475"},"modified":"2024-04-16T18:58:46","modified_gmt":"2024-04-16T18:58:46","slug":"data-types-in-postgresql-learning-postgresql-with-grant","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/postgresql\/data-types-in-postgresql-learning-postgresql-with-grant\/","title":{"rendered":"Data Types in PostgreSQL: Learning PostgreSQL with Grant"},"content":{"rendered":"<p><em><strong>This is part of an ongoing series of post by Grant as he takes his vast knowledge of SQL Server and applies it to adding PostgreSQL and shares it with you so you can skip learn from his triumphs and mistakes. For more you can go to the <a href=\"https:\/\/www.red-gate.com\/simple-talk\/collections\/series-learning-postgresql-with-grant\/\">Learning PostgreSQL with Grant<\/a> series home page<\/strong><\/em><\/p>\n\n<p>When I decided that the next topic to cover would be data types, little did I know what I was getting into. According to the <a href=\"https:\/\/www.postgresql.org\/docs\/9.5\/datatype.html\">official documentation<\/a> for PostgreSQL, there are twenty <em>categories<\/em> of data types. SQL Server only has 35 data types total. I thought about how to go about both learning the data types and writing this article. I\u2019ve decided this article will be just about the categories of data types, and then any interesting bits within those categories. Likewise, I\u2019m not going to drill down on specific data types now. There\u2019s simply too much to cover.<\/p>\n<p>This would also be a good time for a note about my process for learning PostgreSQL and my ability to translate that learning process to you. Understand that while I truly am just learning PostgreSQL, I have a large amount of experience with, and knowledge in, relational data structures. I started out in Paradox back in the 1980s before progressing to work professionally with Sybase, Oracle, Access, and SQL Server. So, while I am learning PostgreSQL from scratch, I\u2019m not learning a lot of the concepts from scratch. As such, I may gloss over information that would be vital to you if this is your first RDBMS.<\/p>\n<p>So, for the data types, I\u2019m going to discuss the 20 categories and call out some interesting facts. However, even at this level, there\u2019s probably some more fundamental aspects of data types you\u2019ll need if you\u2019re just learning for the first time.<\/p>\n<p>One point I want to make up front, and it\u2019s been true about every single data platform I\u2019ve worked with, you really should use the data types as they are intended and not try to force behaviors where they are not appropriate. What do I mean? I mean that a string is a string and that is different from a date, which is different from a number. Can you interchange these reliably? Yes. Should you? No. Stick to using the appropriate data type. That\u2019s as important in PostgreSQL as it is anywhere else.<\/p>\n<p>With that, let\u2019s get started.<\/p>\n<p>Overview of PostgresSQL data types<\/p>\n<table style=\"height: 553px;\" width=\"861\">\n<tbody>\n<tr style=\"height: 496px;\">\n<td style=\"width: 443.609px; height: 496px;\">\u00a0<\/p>\n<p><a href=\"#numeric\">Numeric types<\/a><\/p>\n<p><a href=\"#money\">Monetary types<\/a><\/p>\n<p><a href=\"#character\">Character types<\/a><\/p>\n<p><a href=\"#binary\">Binary data types<\/a><\/p>\n<p><a href=\"#date\">Date\/Time types<\/a><\/p>\n<p><a href=\"#boolean\">Boolean types<\/a><\/p>\n<p><a href=\"#enum\">Enumerated types<\/a><\/p>\n<p><a href=\"#geometric\">Geometric types<\/a><\/p>\n<p><a href=\"#network\">Network address types<\/a><\/p>\n<p><a href=\"#bitstring\">Bit string types<\/a><\/p>\n<\/td>\n<td style=\"width: 401.391px; height: 496px;\">\u00a0<\/p>\n<p><a href=\"#textsearch\">Text search types<\/a><\/p>\n<p><a href=\"#uuid\">UUID types<\/a><\/p>\n<p><a href=\"#json\">JSON types<\/a><\/p>\n<p><a href=\"#array\">Array types<\/a><\/p>\n<p><a href=\"#composite\">Composite types<\/a><\/p>\n<p><a href=\"#range\">Range types<\/a><\/p>\n<p><a href=\"#object\">Object identifier types<\/a><\/p>\n<p><a href=\"#domain\">Domain types<\/a><\/p>\n<p><a href=\"#lsn\">Pg_lsn type<\/a><\/p>\n<p><a href=\"#pseudo\">Pseudo types<\/a><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2 id=\"numeric\">Numeric types<\/h2>\n<p>The numeric types are very straightforward. There are three integer types for holding whole numbers: <code>smallint<\/code>, <code>integer<\/code>, and <code>bigint<\/code>. There are two precision decimal types: <code>numeric<\/code> and <code>decimal<\/code>. Then there are the floating types: <code>real<\/code> and <code>double<\/code> precision, which map to the mathematical constructs of singles and doubles. Finally, there is a set of numeric data types called <code>serial<\/code>, which are not really data types. These are just automatically incrementing integers but set up so you can easily use them when defining a table. They\u2019re based on using a <code>SEQUENCE<\/code> operation, which is available within PostgreSQL.<\/p>\n<p>I love the explanation that, even though these are auto-incrementing columns, you can, and likely will, see gaps. It\u2019s good for that information to be clear right up front.<\/p>\n<p>Except for the <code>serial<\/code> type, the Numeric data types are very straightforward.<\/p>\n<h2 id=\"money\">Monetary types<\/h2>\n<p>Well, that\u2019s misleading. There is exactly one, <code>money<\/code>. The only interesting thing here is that the decimal in <code>money<\/code> is fixed, but you can change it. It\u2019s a database level setting you can adjust within a set range.<\/p>\n<h2 id=\"character\">Character types<\/h2>\n<p>I expected a very long list here and ended up with three: <code>char<\/code>, <code>varchar<\/code> and <code>text<\/code>. The <code>char<\/code> data type is fixed length with padding. This means if you define a column as <code>pettype char(50)<\/code> and you put in the value <em>cat<\/em>, there will be 47 spaces added. The <code>varchar<\/code> data type is the same as variable character in other database systems. The column <code>pettype varchar(50)<\/code> and a value of <em>cat<\/em> means it stores just <em>cat<\/em> without padding. The <code>varchar<\/code> data type has a variable length as opposed to a fixed length string (another term for character). It\u2019s also possible to omit the size for the <code>varchar<\/code> data type. In this case, it can hold any number of characters up to 1 GB.<\/p>\n<p>The <code>text<\/code> type is meant for unlimited data up to 1 GB. It comes with a bunch of wrinkles, same as the similar data type in SQL Server.<\/p>\n<p>The most interesting thing is that there are not separate Unicode data types. Instead, each of these three data types supports Unicode. That\u2019s it. Easy. Honestly, I love this. I\u2019ve always found the <code>VARCHAR\/NVARCHAR<\/code> found in SQL Server construct to be a pain.<\/p>\n<h2 id=\"binary\">Binary Data types<\/h2>\n<p>Again, there is only one, the <code>bytea<\/code> data type. I think I see where this is going. Some of the \u201ctypes\u201d are simply going to be a \u201ctype\u201d. Someone decided that defining them this way was better than just listing \u201cOther\u201d as a type with a bucket full of disparate data types.<\/p>\n<p>Anyway, it\u2019s a binary string called <code>bytea<\/code>. There are some rules and behaviors around escape characters, but basically, it\u2019s for storing binaries like images within your database.<\/p>\n<h2 id=\"date\">Date\/Time types<\/h2>\n<p>I like the naming standards in PostgreSQL. It makes things much more straightforward than other systems I\u2019ve worked with (&lt;cough&gt;SQL Server&lt;\/cough). The timestamp data type stores both date and time. The date data type stores dates, but not times. The time data type stores time, but not dates. Finally, there is an interval data type. The interval data type stores a time interval.<\/p>\n<p>I could spend the rest of this article talking about the interval data type. It\u2019s fascinating. You can define the precise interval, from microseconds to millennia. You can also add a direction by adding <code>ago<\/code> to the input, effectively making it a negative interval.<\/p>\n<p>There are a number of configuration settings for controlling time zone, special values and other behaviors. There are also date and time specific functions as well as date\/time mathematics.<\/p>\n<p>This is one of those data types that frequently get abused. People want a specific format on their dates. Rather than fixing that at the server or application level, they store dates as strings, which is a bad mistake; it removes tons of functionality. Use these data types as intended.<\/p>\n<h2 id=\"boolean\">Boolean type<\/h2>\n<p>There is one Boolean type. <code>Bool<\/code>. It\u2019s on or it\u2019s off. It\u2019s 1 or it\u2019s 0. That\u2019s it.<\/p>\n<h2 id=\"enum\">Enumerated types<\/h2>\n<p>This one is interesting. There is only one <code>enumerated<\/code> type, or there are an infinite number of enumerated types, depending on your point of view. Basically, this is an <code>enum<\/code>, an enumerated list. Let\u2019s define one:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">CREATE TYPE pets AS ENUM ('cat', 'dog', 'horse', 'cockroach');\r\nCREATE TABLE mypets\r\n(mypet pets)<\/pre>\n<p>You can define a data type as a defined list. In this case, only values that make up the <code>enum<\/code> pets can be inserted into the <code>mypet<\/code> column.<\/p>\n<p>I\u2019m going to have to spend some time with this one. It could be amazing, or it could be a performance hellscape. It\u2019s unclear which, but maybe it\u2019s both.<\/p>\n<h2 id=\"geometric\">Geometric types<\/h2>\n<p>The geometric types make up another interesting category. There are a several, from <code>point<\/code>, to <code>line<\/code> <code>segment<\/code>, to <code>circle<\/code>, to the really fun one, path. You have a number of choices. There are also a several <a href=\"https:\/\/www.postgresql.org\/docs\/9.5\/functions-geometry.html\">geometric functions<\/a> that go with these data types. Not much to add to this one. These are only two-dimensional types though. All the types are built off an X\/Y coordinate system.<\/p>\n<h2 id=\"network\">Network Address types<\/h2>\n<p>This is fascinating. Up to this point in the article, all the data types we\u2019ve seen have been pretty standard across database systems I\u2019ve worked with. Oh sure, a few small additions, but nothing quite like these network address types. They\u2019ve defined IPv4, IPv6 and MAC addresses as distinct data types. That ensures that you\u2019ll always input them correctly because of type checking. However, you also get specialized <a href=\"https:\/\/www.postgresql.org\/docs\/9.5\/functions-net.html\">networking functions<\/a>, built right into the database.<\/p>\n<p>Honestly, this is cool. Actually, I\u2019ll go one further, this is what you get from open source software. Sure, you could probably build rules and user-defined data types into, say, a SQL Server database to emulate this. However, the work is on you to do it. There may also be software packages out there to help. Instead, built right into the database is a pretty standard set of needs for computer people.<\/p>\n<p>You get three types:<\/p>\n<ul>\n<li>inet: This is for IPv4 and IPv6 host addresses with an optional netmask<\/li>\n<li>cidr: IPv4 and IPv6 network specification<\/li>\n<li>macaddr: This stores MAC addresses, such as your ethernet card and others.<\/li>\n<\/ul>\n<p>I honestly don\u2019t have an immediate need for these data types, but I\u2019m intrigued at what it might open up in terms of data processing.<\/p>\n<h2 id=\"bitstring\">Bit String types<\/h2>\n<p>Another interesting one. There are two, <code>bit(n)<\/code> and <code>bit varying(n)<\/code>. Similar to a regular string, <code>char<\/code> or <code>varchar<\/code>, you then get a padded fix length column, or a variable, but limited, length column. The goal of the data type is to store and\/or visualize bit masks. I\u2019m not sure if I\u2019d put this to work much, but it\u2019s good to know it\u2019s a possibility.<\/p>\n<h2 id=\"textsearch\">Text Search types<\/h2>\n<p>This is interesting. There is a text data type, mentioned earlier, as a part of the Character Types. However, evidently, you can\u2019t put full text search capabilities onto that column type. Instead, you need to use one of the two text search types, <code>tsvector<\/code> and <code>tsquery<\/code>.<\/p>\n<p>These concepts get complicated quickly.<\/p>\n<p>The <code>tsvector<\/code> consists of a list of lexemes (basically, words stored, but variants of the same word are merged together). Take a phrase like this one:<\/p>\n<p>\u2018I do not like green eggs and ham. I do not like them Sam-I-Am\u2019<\/p>\n<p>It would be stored as such:<\/p>\n<p>\u2018and\u2019 \u2018do\u2019 \u2018eggs\u2019 \u2018green\u2019 \u2018ham\u2019 \u2018I\u2019 \u2018like\u2019 \u2018not\u2019 \u2018Sam-I-Am\u2019 \u2018them\u2019<\/p>\n<p>You can see that the second set of \u2018I do not like\u2019 was eliminated, and the words have been alphabetized. That\u2019s all done in the background. Oh, and it gets more complicated. There are also ways to define location within the string for proximity searches. You can also update your lexemes to provide them with weight to change what gets output from full text queries and what gets eliminated. You then get to the functions for dealing with the searches.<\/p>\n<p>Speaking of searches, <code>tsquery<\/code> is where they get stored. This one stores the lexemes, as above, but then puts together groupings using logical operators <code>$ (AND), | (OR), and ! (NOT)<\/code>. You can also control the logic with parenthesis.<\/p>\n<p>I could go down this rabbit hole for a long time. I\u2019ll leave it here for now since there is more to cover.<\/p>\n<h2 id=\"uuid\">UUID type<\/h2>\n<p>Universally Unique Identifiers (<code>UUID<\/code>) which is the same as a Globally Unique Identifier (GUID). Interestingly, the database system itself can\u2019t generate <code>UUID<\/code> but instead relies on external modules to do the work.<\/p>\n<h2 id=\"json\">JSON types<\/h2>\n<p>What? No YAML?<\/p>\n<p>There are two, <code>json<\/code> and <code>jsonb<\/code>. There are two key differences between them, both on the <code>jsonb<\/code> side. <code>Jsonb<\/code> is stored as a binary instead of as a string, making it slower to store and retrieve, but making it much faster to process JSON searches. Speaking of searches, <code>jsonb<\/code> also supports indexes.<\/p>\n<p>The recommendation in the documentation is that <code>jsonb<\/code> will be better for most use-cases. The json data type keeps all formatting in place and doesn\u2019t allow for any reordering of the keys within a JSON document. For most people, most of the time, I can see why none of that would matter.<\/p>\n<p>The <code>jsonb<\/code> storage also works with primitive data types within the JSON documents, so you can ensure that <code>text<\/code> is text, <code>numerics<\/code> are, you know, numbers, <code>bools<\/code> are Booleans and a <code>null<\/code> value is, not null but <code>(none)<\/code> because null means something else entirely in SQL.<\/p>\n<p>In addition to the indexing, <code>jsonb<\/code> also has the capability to determine containment, meaning one JSON document is stored within another.<\/p>\n<p>There are also a ton of functions supporting JSON as well.<\/p>\n<h2 id=\"array\">Array types<\/h2>\n<p>The documentation just says \u201cArrays\u201d, being the only one without the word \u201cType\u201d next to it. I put it back in there.<\/p>\n<p>Honestly, I\u2019d look upon this as the equivalent of SQL Server\u2019s <code>VARIANT<\/code> data type. In short, poison.<\/p>\n<p>Basically, you can now define a column in your database as a variable-length, multidimensional array, including all built-in, user-defined, enum and composite types. It gets better.<\/p>\n<p>The documentation says: \u201cThe syntax for <code>CREATE<\/code> <code>TABLE<\/code> allows the exact size of arrays to be specified\u2026\u201d. It then follows that up with \u201cHowever, the current implementation ignores any supplied array size limits\u2026\u201d<\/p>\n<p>If you recall earlier, I said that the Network Types were an example of the benefits you can receive from open-source software. I\u2019d say this bit of functionality is an example of the punishment you can receive from open-source software. Oh, I get it. We want to store anything, anywhere, at any time, any way we can, because it makes things \u201ceasy\u201d. This is great until you have to maintain that stuff, performance tune it, ensure data integrity, clean up the mess made by poorly disciplined developers who can put any sized array they want to with anything in it, and there\u2019s almost nothing we can do to stop them.<\/p>\n<p>Look. Don\u2019t do this.<\/p>\n<p>The examples of using arrays I keep finding online are \u201cHey, you know what you can do instead of normalizing your data structures\u2026\u201d Yeah, watch performance tank. OK, maybe not. There are Generalized Inverted Indexes (GIN). These allow for indexing values such that the internals are composites.<\/p>\n<p>There\u2019s a lot to unpack here. However, I stand by my assessment, especially after doing searches to see if people have problems with performance using arrays. They do. I found this quote: \u201cWhy don&#8217;t you normalize your data? That will fix all problems, including many problems you didn&#8217;t encounter yet.\u201d<\/p>\n<p>As I get into this deeper, at some point, lots of testing will be needed to understand if this is good or bad.<\/p>\n<h2 id=\"composite\">Composite types<\/h2>\n<p>This type is another odd one.<\/p>\n<p>When you create a table, you also get a composite type created at the same time. You can then use the composite type as a column in another table. Then, that other table gets, effectively, a table in its column. Now, if that sounds a lot like an array, I think I\u2019d agree. Further, no constraints, even if they\u2019re defined in your original table, will be enforced within a composite type. Also, you can\u2019t create any new constraints for a composite type.<\/p>\n<p>You can also create a composite type as a standalone object. I had to see this in action, so I ran the following script:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">CREATE\u00a0TYPE\u00a0microphone\u00a0AS\u00a0(\r\n\u00a0\u00a0\u00a0\u00a0waterproof\u00a0boolean,\r\n\u00a0\u00a0\u00a0\u00a0speaker\u00a0boolean,\r\n\u00a0\u00a0\u00a0\u00a0earpiece\u00a0boolean\r\n);\r\nCREATE\u00a0TABLE\u00a0radio\u00a0(\r\n\u00a0\u00a0\u00a0\u00a0radioname\u00a0VARCHAR(50),\r\n\u00a0\u00a0\u00a0\u00a0mic\u00a0microphone\r\n);\r\nINSERT\u00a0INTO\u00a0radio\u00a0(mic,radioname)\u00a0VALUES\u00a0('(1,1,0)','Yaesu\u00a08900');\r\nSELECT\u00a0*\u00a0FROM\u00a0radio;<\/pre>\n<p>The result is here:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"335\" height=\"138\" class=\"wp-image-93476\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2022\/03\/word-image.png\" \/><\/p>\n<p>OK. That\u2019s pretty interesting. Again, what happens with indexing? Performance? Lots more to learn here.<\/p>\n<h2 id=\"range\">Range types<\/h2>\n<p>This is another really interesting one. You can create a range of values based on a subype, another data type. There are a number of built-in range types, and you can create your own. The built in ones are:<\/p>\n<ul>\n<li>int4range \u2013 a range of integers<\/li>\n<li>int8range \u2013 a range of big integers<\/li>\n<li>numrange \u2013 a range based on numeric<\/li>\n<li>tsrange \u2013 timestamps, date\/time, but without a time zone<\/li>\n<li>tstzrange \u2013 same as above, but with a time zone<\/li>\n<li>daterange \u2013 range of date<\/li>\n<\/ul>\n<p>Once you define ranges, then you get range functionality, upper bound, containment, overlap, intersection, stuff like that. It\u2019s another fascinating data type. It\u2019s also another array-style data type. I see why PostgreSQL is sometimes referred to as an object database. It\u2019s mostly relational, but it has a lot of this kind of stuff in it that is clearly meant to work more with objects.<\/p>\n<h2 id=\"object\">Object Identifier types<\/h2>\n<p>These are meant to be internal identifiers for system tables. It\u2019s only a four-byte integer, so they don\u2019t recommend its use as a primary key. However, you can use it to refer to system tables and system table identifiers within your tables. There several of these types, all referring back to objects within the database. For example:<\/p>\n<ul>\n<li>regproc \u2013 stored procedures and functions<\/li>\n<li>regrole \u2013 roles<\/li>\n<li>regtype \u2013 data types, our topic today<\/li>\n<\/ul>\n<p>Interestingly, there are warnings in the documentation about the use of the oid and various types that will lead to \u201csub-optimal planning\u201d. Based on the information around that, I think it means that the optimizer will make some poor choices when using these.<\/p>\n<h2 id=\"domain\">Domain types<\/h2>\n<p>A domain type is simply a user-defined data type. You can create the specified object type, but also add restrictions to it. The example shown in the documentation is defining a new data type as a positive integer. There\u2019s no suggestion of restrictions, so I\u2019m assuming any of the data types listed here would be supported as a domain type.<\/p>\n<h2 id=\"lsn\">pg_lsn type<\/h2>\n<p>I\u2019m not sure why they don\u2019t just call this what it is, the Log Sequence Number (LSN) type. You can store pointers to the actual LSN in the logs. Further, you can do functions on them, like determine which LSN is greater (newer) and other functions, all related to the log and the transactions stored there.<\/p>\n<h2 id=\"pseudo\">Psuedo types<\/h2>\n<p>These are, for want of a better way to explain it, not quite data types. You can\u2019t use them in column definitions. You can however use them as function arguments and result types. It\u2019s a really wide list of behaviors. Let me give you a few examples:<\/p>\n<ul>\n<li>anyarray \u2013 a function will accept any array type<\/li>\n<li>void \u2013 a function that doesn\u2019t return any value at all<\/li>\n<li>record \u2013 this function will take any kind of unspecified row<\/li>\n<\/ul>\n<p>Some interesting caveats appear in the documentation. Evidently you can only use these for internal processing, except for void and record. That\u2019s because most procedural languages don\u2019t recognize these types.<\/p>\n<h2>PostgreSQL data types<\/h2>\n<p>I\u2019m so glad I decided to walk through all these different data types. I can now see substantial differentiation between PostgreSQL and other relational data stores. I also see why others have referred to PostgreSQL as an object database. I don\u2019t believe that to be the case, but you can absolutely see where that\u2019s coming from, heck, creating a type for a table, automatically. I also found the generally mundane data types reassuring, that I can get the standard work done, as well as crazy stuff like defining data ranges within a single column. Finally, it was interesting that, despite this very wide variety of data types, there was no geography type. Looking it up, sure enough, there\u2019s an extension you can add that supports it, so, that means, there are likely extensions for all sorts of other data types as well.<\/p>\n<p>Remember, the code for this series is <a href=\"https:\/\/github.com\/ScaryDBA\/LearningPostgre\">available on GitHub<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PostgreSQL has an unusually large number of data types. Grant Fritchey reviews each data type and discusses the good and bad points of each.&hellip;<\/p>\n","protected":false},"author":221792,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,143534],"tags":[95506,158977,159066],"coauthors":[6785],"class_list":["post-93475","post","type-post","status-publish","format-standard","hentry","category-featured","category-postgresql","tag-automate","tag-learningpostgresqlwithgrant","tag-postgresql-101-webinar-sidebar"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93475","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\/221792"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=93475"}],"version-history":[{"count":14,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93475\/revisions"}],"predecessor-version":[{"id":101682,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/93475\/revisions\/101682"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=93475"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=93475"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=93475"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=93475"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}