{"id":77704,"date":"2018-03-22T19:27:39","date_gmt":"2018-03-22T19:27:39","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=77704"},"modified":"2021-09-29T16:21:06","modified_gmt":"2021-09-29T16:21:06","slug":"sql-server-graph-databases-part-2-querying-data-graph-database","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/sql-server-graph-databases-part-2-querying-data-graph-database\/","title":{"rendered":"SQL Server Graph Databases \u2013 Part 2: Querying Data in a Graph Database"},"content":{"rendered":"<h4>The series so far:<\/h4>\n<ol>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/sql-development\/sql-server-graph-databases-part-1-introduction\/\">SQL Server Graph Databases - Part 1: Introduction<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/t-sql-programming\/sql-server-graph-databases-part-2-querying-data-graph-database\/\">SQL Server Graph Databases - Part 2: Querying Data in a Graph Database<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/t-sql-programming\/sql-server-graph-databases-part-3-modifying-data-graph-database\/\">SQL Server Graph Databases - Part 3: Modifying Data in a Graph Database<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/t-sql-programming\/sql-server-graph-databases-part-4-working-hierarchical-data-graph-database\">SQL Server Graph Databases - Part 4: Working with hierarchical data in a graph database<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/t-sql-programming\/sql-server-graph-databases-part-5-importing-relational-data-graph-database\/\">SQL Server Graph Databases - Part 5:\u00a0Importing Relational Data into a Graph Database<\/a><\/li>\n<\/ol>\n\n<p>Microsoft incorporated the graph database in SQL Server 2017, providing a logical structure for storing and querying data sets that contain complex many-to-many or hierarchical relationships. The first article in this series introduced you to the basics of graph databases and described how to define node and edge tables and populate them with data. In this article, we turn to the querying side of the equation, with a focus on retrieving related data in multiple node tables.<\/p>\n<p>For the examples in this article, I used the <strong>FishGraph<\/strong> database from the first article in this series, except that I added more sample data. The database is based on a fictitious fish-lovers forum and includes three node tables (<strong>FishSpecies<\/strong>, <strong>FishLover<\/strong>, and <strong>FishPost<\/strong>) and three edge tables (<strong>Likes<\/strong>, <strong>Posts<\/strong>, and <strong>LinksTo<\/strong>). The following figure shows the data model used to build the database.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1488\" height=\"904\" class=\"wp-image-77705\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-83.png\" \/><\/p>\n<p>The rectangles represent the nodes, and the arrows connecting the nodes represent the edges, with the arrows pointing in the direction of the relationships. You can download the T-SQL script used to create and populate the database at the bottom of this article.<\/p>\n<h2>Introducing the MATCH Function<\/h2>\n<p>For the most part, querying tables in a graph database works much the same way as querying regular relational tables, although there are some limitations, such as not being able to perform cross-database queries on graph tables. (For more information about graph database limitations, refer to the Microsoft document <a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/relational-databases\/graphs\/sql-graph-architecture\">SQL Graph Architecture<\/a>.)<\/p>\n<p>Despite the limitations, you should find that most queries work as expected. For example, the following <strong>SELECT<\/strong> statement joins the <strong>FishLover<\/strong>, <strong>Likes<\/strong>, and <strong>FishSpecies<\/strong> tables in order to retrieve a list of users who like certain fish species:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT fl.Username, fs.CommonName, fs.ScientificName\r\n  FROM FishLover fl INNER JOIN Likes lk\r\n      ON fl.$node_id = lk.$from_id\r\n    INNER JOIN FishSpecies fs\r\n      ON lk.$to_id = fs.$node_id;<\/pre>\n<p>The <strong>SELECT<\/strong> statement uses the <strong>$node_id<\/strong>, <strong>$from_id<\/strong>, and <strong>$to_id<\/strong> column aliases to join the tables and return the data shown in the following figure<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"886\" height=\"406\" class=\"wp-image-77706\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-84.png\" \/><\/p>\n<p>As you can see, querying graph tables is a fairly straightforward process, especially when you take advantage of the graph column aliases. Of course, if you\u2019re trying to retrieve data based on more complex relationships, the query itself also becomes more complex and can even get a bit unwieldy. For this reason, Microsoft has added the <strong>MATCH<\/strong> function for retrieving related data from graph tables.<\/p>\n<p>The <strong>MATCH<\/strong> function lets you define a search pattern based on the relationships between nodes. You can use the function only in the <strong>WHERE<\/strong> clause of a <strong>SELECT<\/strong> statement that queries node and edge tables. The following syntax shows the elements that go into defining the search pattern:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">MATCH(&lt;search_pattern&gt;)\r\n&lt;search_pattern&gt;::=\r\n    &lt;node_alias&gt;\r\n    { -( &lt;edge_alias&gt; )-&gt; | &lt;-( &lt;edge_alias&gt; )- }\r\n    &lt;node_alias&gt;\r\n    [ { AND &lt;search_pattern&gt; } [ ...n ] ]\r\n  &lt;node_alias&gt; ::=\r\n    node_table_name | node_alias \r\n  &lt;edge_alias&gt; ::=\r\n    edge_table_name | edge_alias<\/pre>\n<p>A search pattern can define one or more relationships. For each relationship, you must identify the originating and terminating nodes, as well as the edge that ties the two nodes together. You must also specify the direction of the relationship, using dashes and arrows, with the edge situated between the two nodes. For example, if you want to define a single relationship that originates with <strong>node1<\/strong> and terminates with <strong>node2<\/strong>, you would use the following syntax for your <strong>WHERE<\/strong> clause:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">WHERE MATCH(node1-(edge)-&gt;node2)<\/pre>\n<p>Notice that the edge is enclosed in parentheses, with a dash preceding the edge, and a dash and right arrow following the edge. This defines a relationship that moves from left-to-right. You can reverse this order by specifying <strong>node1<\/strong> on the right side of the search pattern and <strong>node2<\/strong> on the left side, with the arrow pointing in the opposite direction:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">WHERE MATCH(node2&lt;-(edge)-node1)<\/pre>\n<p>In either case, the search pattern indicates that the <strong>WHERE<\/strong> clause should return only those rows in which a relationship exists between <strong>node1<\/strong> (the originating node) and <strong>node2<\/strong> (the terminating node), as defined in the <strong>edge<\/strong> element.<\/p>\n<p>With these basics in mind, you can rewrite the <strong>SELECT<\/strong> statement above to simplify the query:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Species.CommonName, Species.ScientificName\r\nFROM FishLover Lover, Likes, FishSpecies Species\r\nWHERE MATCH(Lover-(Likes)-&gt;Species);<\/pre>\n<p>In the <strong>FROM<\/strong> clause, you simply list the participating tables \u2013 without the <strong>ON<\/strong> clause&#8211; providing table aliases where appropriate. You can then reference the aliases in the search pattern of the <strong>MATCH<\/strong> function. In this case, the search pattern defines the relationship <em>fish lover likes a fish species<\/em>. The statement will return the same results as those returned by the <strong>SELECT<\/strong> statement above.<\/p>\n<p>You can also reverse the order of the relationship so that it is defined from right-to-left:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Species.CommonName, Species.ScientificName\r\nFROM FishLover Lover, Likes, FishSpecies Species\r\nWHERE MATCH(Species&lt;-(Likes)-Lover);<\/pre>\n<p>Again, the <strong>SELECT<\/strong> statement returns the same results as the previous two <strong>SELECT<\/strong> statements.<\/p>\n<p>You can include other elements in the <strong>WHERE<\/strong> clause, in addition to the <strong>MATCH<\/strong> function. For example, the following <strong>WHERE<\/strong> clause adds a search condition specifying that only rows with a <strong>Username<\/strong> value of <strong>hooked<\/strong> should be returned:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Species.CommonName, Species.ScientificName\r\nFROM FishLover Lover, Likes, FishSpecies Species\r\nWHERE MATCH(Lover-(Likes)-&gt;Species)\r\n  AND Lover.Username = 'hooked';<\/pre>\n<p>The statement now returns the results shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"542\" height=\"212\" class=\"wp-image-77707\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-85.png\" \/><\/p>\n<p>As you can see, using the <strong>MATCH<\/strong> function to define a search pattern based on a single relationship is a fairly straightforward process. In many cases, however, you\u2019ll want to return data based on multiple relationships, which is where the function can be particularly handy.<\/p>\n<h2>Creating Compound MATCH Expressions<\/h2>\n<p>If you refer back to the syntax for the <strong>MATCH<\/strong> function, you\u2019ll notice that you can use the <strong>AND<\/strong> operator when defining your search pattern, allowing you to string together multiple relationships within a single expression. Note, however, that the <strong>MATCH<\/strong> function does not support the <strong>OR<\/strong> operator or the <strong>NOT<\/strong> operator, so the logic you can define is somewhat limited. Even so, the <strong>AND<\/strong> operator can still be very useful. For example, the following search pattern uses the operator to string together two relationships:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Post.Title, Species.CommonName\r\nFROM FishLover Lover, Likes, FishPost Post, LinksTo, FishSpecies Species\r\nWHERE MATCH(Lover-(Likes)-&gt;Post AND Post-(LinksTo)-&gt;Species);<\/pre>\n<p>For the <strong>SELECT<\/strong> statement to return a row, a fish lover must like a fish post <em>and<\/em> the fish post must link to a fish species. In this case, the statement returns only two rows, as shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"204\" class=\"wp-image-77708\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-86.png\" \/><\/p>\n<p>By being able to link together multiple relationships, you can dig more deeply into how the nodes in a graph database are interconnected. For example, the preceding <strong>SELECT<\/strong> statement might help to determine whether users are more inclined to like a post that specifically links to a fish species.<\/p>\n<p>In some cases, you can link together relationships without using the <strong>AND<\/strong> operator, as long as your search pattern defines the same logic. For instance, you can rewrite the preceding <strong>SELECT<\/strong> statement by eliminating the <strong>AND<\/strong> operator and one of the references to the <strong>Post<\/strong> table alias:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Post.Title, Species.CommonName\r\nFROM FishLover Lover, Likes, FishPost Post, LinksTo, FishSpecies Species\r\nWHERE MATCH(Lover-(Likes)-&gt;Post-(LinksTo)-&gt;Species);<\/pre>\n<p>The <strong>SELECT<\/strong> statement returns the same results as the preceding one, even though the search pattern has been simplified. You can also define a search pattern that contains two relationships terminating with the same node, as in the following example:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Species.CommonName, Post.Title\r\nFROM FishLover Lover, Likes, FishSpecies Species, FishPost Post, LinksTo\r\nWHERE MATCH(Lover-(Likes)-&gt;Species&lt;-(LinksTo)-Post);<\/pre>\n<p>The first relationship (<em>fish lover likes a fish species<\/em>) is defined from left-to right, and the second relationship (<em>fish post links to a fish species<\/em>) is defined from right-to-left. As a result, the <strong>SELECT<\/strong> statement returns only those rows in which a fish species is both liked and linked to, giving us the results shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"216\" class=\"wp-image-77709\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-87.png\" \/><\/p>\n<p>You can also define search patterns that include more than two relationships, using the <strong>AND<\/strong> operator where appropriate. For example, the search pattern in the following <strong>SELECT<\/strong> statement includes three relationships but only one instance of the <strong>AND<\/strong> operator:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Post.Title, Species.CommonName\r\nFROM FishLover Lover, Likes Likes1, FishPost Post, \r\n  LinksTo, FishSpecies Species, Likes Likes2\r\nWHERE MATCH(Lover-(Likes1)-&gt;Post-(LinksTo)-&gt;Species \r\n  AND Lover-(Likes2)-&gt;Species);<\/pre>\n<p>Because the <strong>Likes<\/strong> table is referenced twice within the search pattern, it must be included twice in the <strong>FROM<\/strong> clause, with a different alias assigned to each instance. The search pattern then uses these aliases when defining the three relationships (<em>fish lover likes a fish post, fish post links to a fish species,<\/em> and <em>fish lover likes a fish species<\/em>). The <strong>SELECT<\/strong> statement will return only those rows in which a fish species is both liked and linked to from a post that is liked, as shown in the following figure.<\/p>\n<p>In this case, the user <strong>underwatercasey<\/strong> likes both the fish post and fish species, and the fish post links to the fish species. You can also rewrite the search pattern to eliminate the <strong>AND<\/strong> operator altogether:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, Post.Title, Species.CommonName\r\nFROM FishLover Lover, Likes Likes1, FishPost Post, \r\n  LinksTo, FishSpecies Species, Likes Likes2\r\nWHERE MATCH(Lover-(Likes1)-&gt;Post-(LinksTo)-&gt;Species&lt;-(Likes2)-Lover);<\/pre>\n<p>The <strong>SELECT<\/strong> statement returns the same results as the preceding statement but simplifies the search pattern. In some cases, however, you might find that the <strong>AND<\/strong> operator makes it easier to read and troubleshoot your code as you heap on more and more relationships.<\/p>\n<h2>Defining a Self-referencing Query<\/h2>\n<p>Because of the way in which a graph database is structured, it is just as easy to perform a self-referencing query as any other type of query. For example, the following <strong>SELECT<\/strong> statement returns a list of fish posts that link to other posts:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Post1.Title Title1, Post2.Title Title2\r\nFROM FishPost Post1, LinksTo, FishPost Post2\r\nWHERE MATCH(Post1-(LinksTo)-&gt;Post2);<\/pre>\n<p>To define the relationship in the search pattern, you must include two instances of the <strong>FishPost<\/strong> table in the <strong>FROM<\/strong> clause, assigning a different alias to each instance, similar to how you included multiple instances of the <strong>Likes<\/strong> edge table in the preceding two examples. The <strong>SELECT<\/strong> statement returns the results shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"290\" class=\"wp-image-77711\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-89.png\" \/><\/p>\n<p>You can use the same logic to determine which fish lovers like other fish lovers:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover1.Username User1, Lover2.Username User2\r\nFROM FishLover Lover1, Likes, FishLover Lover2\r\nWHERE MATCH(Lover1-(Likes)-&gt;Lover2);<\/pre>\n<p>This time the <strong>FROM<\/strong> clause includes two instances of the <strong>FishLover<\/strong> table, with a unique alias assigned to each one, giving us the results shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"308\" class=\"wp-image-77712\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-90.png\" \/><\/p>\n<p>You can also use this approach when defining more than two relationships in your search pattern. For example, the following <strong>SELECT<\/strong> statement returns a list of users that are liked by user <strong>hooked<\/strong>, along with the users that they like:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover2.Username User2, Lover3.Username User3\r\nFROM FishLover Lover1, Likes Likes1, FishLover Lover2, \r\n  Likes Likes2, FishLover Lover3\r\nWHERE MATCH(Lover1-(Likes1)-&gt;Lover2-(Likes2)-&gt;Lover3)\r\n  AND Lover1.Username = 'hooked';<\/pre>\n<p>The <strong>FROM<\/strong> clause now includes three instances of the <strong>FishLover<\/strong> table and two instances of the <strong>Likes<\/strong> table. The search pattern uses these instances to define the relationships <em>fish lover1 likes fish lover2<\/em> and <em>fish lover2 likes fish lover3,<\/em> giving us the results shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"490\" height=\"220\" class=\"wp-image-77713\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-91.png\" \/><\/p>\n<p>Essentially what we have here is a friend-of-a-friend type scenario:<\/p>\n<ul>\n<li>The user <strong>hooked<\/strong> likes the users <strong>powerangler<\/strong> and <strong>deepdive<\/strong>.<\/li>\n<li>The user <strong>powerangler<\/strong> likes the user <strong>deepdive<\/strong>.<\/li>\n<li>The user <strong>deepdive<\/strong> likes the user <strong>underwatercasey<\/strong>.<\/li>\n<\/ul>\n<p>Self-referencing queries make it easy to discover how data is related wherever it resides. Because the relationships are stored within the edge tables, it does not matter if the relationships cross multiple nodes, are contained within a single node, or are a combination of both.<\/p>\n<h2>Combining the MATCH Function with Other T-SQL Features<\/h2>\n<p>So far in this article, the <strong>SELECT<\/strong> statements we\u2019ve covered have included only the <strong>SELECT<\/strong>, <strong>FROM<\/strong>, and <strong>WHERE<\/strong> clauses. However, you can use the <strong>MATCH<\/strong> function with other query types, such as queries that group and aggregate data. For example, the following <strong>SELECT<\/strong> statement includes the <strong>GROUP<\/strong> <strong>BY<\/strong> and <strong>ORDER<\/strong> <strong>BY<\/strong> clauses:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">SELECT Lover.Username, COUNT(*) AS TotalLikes\r\nFROM FishLover Lover, Likes, FishSpecies Species\r\nWHERE MATCH(Lover-(Likes)-&gt;Species)\r\nGROUP BY Lover.Username\r\nORDER BY Username;<\/pre>\n<p>The <strong>GROUP<\/strong> <strong>BY<\/strong> clause groups the data by the <strong>Username<\/strong> values in the <strong>FishLover<\/strong> table in order to provide a count of total likes per user, as shown in the following results.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"464\" height=\"354\" class=\"wp-image-77714\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-92.png\" \/><\/p>\n<p>Although this is a fairly basic example, it demonstrates how you can build various types of queries based on data from a graph database, just like queries against relational tables. You can even use a graph database in conjunction with Microsoft Machine Learning Services (MLS). For example, the following T-SQL script retrieves data from a graph database and then uses it in a Python script to generate a bar chart:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">DECLARE @pscript NVARCHAR(MAX);\r\nSET @pscript = N'\r\n# import matplotlib modules\r\nimport matplotlib\r\nmatplotlib.use(\"PDF\")\r\nimport matplotlib.pyplot as plt\r\n   \r\n# define df data frame\r\ndf = InputDataSet\r\n   \r\n# create bar chart object\r\npt = df.plot.barh()\r\npt.set_yticklabels(labels=df.Username)\r\n   \r\n# save bar chart to PDF file\r\nplt.savefig(\"c:\\\\datafiles\\\\TotalFishLikes.pdf\", \r\n  bbox_inches=\"tight\", pad_inches=.5)';\r\n   \r\nDECLARE @sqlscript NVARCHAR(MAX);\r\nSET @sqlscript = N'\r\n  SELECT Lover.Username, COUNT(*) AS TotalLikes\r\n  FROM FishLover Lover, Likes, FishSpecies Species\r\n  WHERE MATCH(Lover-(Likes)-&gt;Species)\r\n  GROUP BY Lover.Username\r\n  ORDER BY Username DESC;';\r\n   \r\nEXEC sp_execute_external_script\r\n  @language = N'Python',\r\n  @script = @pscript,\r\n  @input_data_1 = @sqlscript;\r\nGO<\/pre>\n<p>I won\u2019t go into too much detail about running the Python script because I covered it in my series on Python and MLS. (The series starts with the article <a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/bi\/machine-learning-services-part-1-python\/\">SQL Server Machine Learning Services \u2013 Part 1: Python Basics<\/a>.) Basically, the T-SQL script does the following:<\/p>\n<ul>\n<li>Declares the <strong>@pscript<\/strong> variable and assigns the Python script to the variable. The script creates a data frame based on the data returned from the graph database and then generates a bar chart based on the data.<\/li>\n<li>Declares the <strong>@sqlscript<\/strong> variable and assigns the <strong>SELECT<\/strong> statement to the variable. This is the same <strong>SELECT<\/strong> statement shown in the previous example.<\/li>\n<li>Passes in the two variables as parameter values to the <strong>sp_execute_external_script<\/strong> stored procedure, which retrieves the graph data and runs the Python code.<\/li>\n<\/ul>\n<p>When you run the <strong>sp_execute_external_script<\/strong> stored procedure, the Python engine generates the bar chart shown in the following figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1722\" height=\"1162\" class=\"wp-image-77715\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2018\/03\/word-image-93.png\" \/><\/p>\n<p>As these examples demonstrate, graph databases have been well integrated into the SQL Server ecosystem, providing you with a great deal of flexibility for working with graph data. MLS in particular opens up a wide range of possibilities for analyzing and visualizing the data in a variety of ways.<\/p>\n<h2>Conclusion<\/h2>\n<p>As with storing and populating graph tables, querying those tables is a relatively painless process, once you understand the fundamentals. Where applicable, you can use the <strong>MATCH<\/strong> function to streamline your queries. When that\u2019s not practical, you can revert to regular queries to get the data you need. The only trick is to make sure you\u2019re working against an instance of SQL Server 2017 and not an earlier version. Fortunately, you can download the Developer\u2019s edition for free, which comes with all the features available to the Enterprise edition, including support for graph databases. You can then use what you learned so far in this series to start exploring graph databases on your own.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Along with Graph Databases, Microsoft has introduced the new MATCH function for querying them. Robert Sheldon explains how to use the new function.&hellip;<\/p>\n","protected":false},"author":221841,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143531],"tags":[5134],"coauthors":[6779],"class_list":["post-77704","post","type-post","status-publish","format-standard","hentry","category-t-sql-programming-sql-server","tag-sql-prompt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/77704","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\/221841"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=77704"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/77704\/revisions"}],"predecessor-version":[{"id":77767,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/77704\/revisions\/77767"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=77704"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=77704"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=77704"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=77704"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}