{"id":15601,"date":"2021-02-07T14:10:37","date_gmt":"2021-02-07T13:10:37","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/"},"modified":"2021-02-07T14:10:37","modified_gmt":"2021-02-07T13:10:37","slug":"an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/","title":{"rendered":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types"},"content":{"rendered":"<p>This is part two of the little series about server side programming in PostgreSQL. In the <a href=\"https:\/\/www.dbi-services.com\/blog\/an-introduction-to-server-side-programming-in-postgresql-1-sql-functions-basics\/\" target=\"_blank\" rel=\"noopener\">last post<\/a> we had a look at the basics when it comes to SQL functions. We learned how to write those functions, how we can pass parameters to functions, how to name parameters for better readability, how to return a result, and how we can use functions in plain SQL statements. In this post we&#8217;ll go a step further and will have a look at how you can use sets, user defined defined types, and polymorphic types. What we will see here is not only true for SQL functions, but also for <a href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\" target=\"_blank\" rel=\"noopener\">PL\/pgSQL<\/a> procedures and functions as we will see in another post.<\/p>\n<p><!--more--><\/p>\n<p>If we go back to one of the function we&#8217;ve defined in the last post:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_bid_for_aid (pn_aid int) returns int\npostgres-#            as $my_tag$\npostgres$#            select bid from pgbench_accounts where aid = pn_aid;\npostgres$#            $my_tag$ language SQL;\nCREATE FUNCTION\n<\/pre>\n<p>This function is returning exactly one result (or nothing, when there is nothing found for a given aid). This might be what you want, but sometimes it is more convenient to return a whole result set (and that is what SQL is made for, it is a set based language). What do we need to change, to make this function returning a result set instead of a single row? Here is one way of doing it:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_bid_for_aid_set (pn_aid_from pgbench_accounts.aid%type, pn_aid_to pgbench_accounts.aid%type) returns setof pgbench_accounts.bid%type\npostgres-#            as $my_tag$\npostgres$#            select bid from pgbench_accounts \npostgres$#                      where aid &gt;= pn_aid_from\npostgres$#                        and aid &lt;= pn_aid_to;\npostgres$#            $my_tag$ language SQL;\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nNOTICE:  type reference pgbench_accounts.bid%TYPE converted to integer\nCREATE FUNCTION\n<\/pre>\n<p>Here is what changed:<\/p>\n<ul>\n<li>We added one additional parameter and changed the parameters from a static data type to dynamically use the data type of the underlying column<\/li>\n<li>What the function will be returning is a set of bids, which means potentially more than one row<\/li>\n<li>Of course the statement needs to fetch more than one row, so this has changed as well<\/li>\n<\/ul>\n<p>You may have noticed that PostgreSQL automatically converted the data types of the parameters and the return data type to integer. You&#8217;ll also see that when you describe the function:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# df get_bid_for_aid_set\n                                        List of functions\n Schema |        Name         | Result data type |          Argument data types           | Type \n--------+---------------------+------------------+----------------------------------------+------\n public | get_bid_for_aid_set | SETOF integer    | pn_aid_from integer, pn_aid_to integer | func\n(1 row)\n<\/pre>\n<p>Once we call the new function we&#8217;ll see that the return is a set:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# select * from get_bid_for_aid_set(pn_aid_from=&gt;1,pn_aid_to=&gt;10);\n get_bid_for_aid_set \n---------------------\n                   1\n                   1\n                   1\n                   1\n                   1\n                   1\n                   1\n                   1\n                   1\n(9 rows)\n<\/pre>\n<p>This is, of course, much better then using the previous function that only return one row for each input as it reduces the amount of calls from ten to one. We still can ask for one row but now we flexible enough to return as much as we want. You can also return a subset of the whole table when using setof;<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_all_for_aid_set (pn_aid_from pgbench_accounts.aid%type, pn_aid_to pgbench_accounts.aid%type) returns setof pgbench_accounts\n                      as $my_tag$\n                      select * from pgbench_accounts \n                              where aid &gt;= pn_aid_from\n                               and aid &lt;= pn_aid_to;\n                      $my_tag$ language SQL;\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nCREATE FUNCTION\n<\/pre>\n<p>This will return all columns from the table as a set:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# select * from get_all_for_aid_set(pn_aid_from=&gt;1,pn_aid_to=&gt;10);\n aid | bid | abalance |                                        filler                                        \n-----+-----+----------+--------------------------------------------------------------------------------------\n   2 |   1 |        0 |                                                                                     \n   3 |   1 |        0 |                                                                                     \n   4 |   1 |        0 |                                                                                     \n   5 |   1 |        0 |                                                                                     \n   6 |   1 |        0 |                                                                                     \n   7 |   1 |        0 |                                                                                     \n   8 |   1 |        0 |                                                                                     \n   9 |   1 |        0 |                                                                                     \n  10 |   1 |        0 |                                                                                     \n(9 rows)\n<\/pre>\n<p>If you have the requirement to work with user defined data types, you can use those in functions as well. Lets consider this simple custom data type:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create type my_type as ( a int, b int );\nCREATE TYPE\npostgres=# d my_type\n          Composite type \"public.my_type\"\n Column |  Type   | Collation | Nullable | Default \n--------+---------+-----------+----------+---------\n a      | integer |           |          | \n b      | integer |           |          | \n<\/pre>\n<p>Using that type in a function follows exactly them same rules as if you work with the base types:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_all_for_custom_type (p_my_type in my_type) returns setof pgbench_accounts\n                       as $my_tag$\n                      select * from pgbench_accounts \n                              where aid &gt;= p_my_type.a\n                               and aid  row(1,5) );\n\npostgres=# select * from get_all_for_custom_type ( p_my_type =&gt; row(1,5) );\n aid | bid | abalance |                                        filler                                        \n-----+-----+----------+--------------------------------------------------------------------------------------\n   2 |   1 |        0 |                                                                                     \n   3 |   1 |        0 |                                                                                     \n   4 |   1 |        0 |                                                                                     \n   5 |   1 |        0 |                                                                                     \n(4 rows)\n<\/pre>\n<p>Using a custom type as a return data type works, not surprises here, as well:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_custom_type (pn_aid in int) returns my_type\n                       as $my_tag$\n                      select row(aid,bid) from pgbench_accounts \n                              where aid = pn_aid;\n                      $my_tag$ language SQL;\nCREATE FUNCTION\npostgres=# select * from get_custom_type(2);\n a | b \n---+---\n 2 | 1\n(1 row)\n<\/pre>\n<p>Another way of returning a set is to the use &#8220;TABLE&#8221; syntax:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_all_table (pn_aid_from pgbench_accounts.aid%type, pn_aid_to pgbench_accounts.aid%type) returns table(aid int,bid int)\n                       as $my_tag$\n                      select aid,bid from pgbench_accounts \n                              where aid &gt;= pn_aid_from\n                               and aid &lt;= pn_aid_to;\n                      $my_tag$ language SQL;\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nNOTICE:  type reference pgbench_accounts.aid%TYPE converted to integer\nCREATE FUNCTION\npostgres=# select * from get_all_table(2,5);\n aid | bid \n-----+-----\n   2 |   1\n   3 |   1\n   4 |   1\n   5 |   1\n(4 rows)\n<\/pre>\n<p>In addition to what we&#8217;ve already seen, PostgreSQL comes with <a href=\"https:\/\/www.postgresql.org\/docs\/current\/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" target=\"_blank\" rel=\"noopener\">Polymorphic Types<\/a>. Using these types you can make a function accepting almost any data type as it&#8217;s input and return:<\/p>\n<pre class=\"brush: sql; gutter: true; first-line: 1\">\npostgres=# create or replace function get_polymorphic (anyelement, anyelement) returns table(aid int,bid int)\n                      as $my_tag$\n                      select aid,bid from pgbench_accounts \n                              where aid &gt;= $1\n                               and aid &lt;= $2;\n                      $my_tag$ language SQL;\nCREATE FUNCTION\npostgres=# select * from get_polymorphic(2,6);\n aid | bid \n-----+-----\n   2 |   1\n   3 |   1\n   4 |   1\n   5 |   1\n   6 |   1\n(5 rows)\n<\/pre>\n<p>That&#8217;s it for now. In the next post we&#8217;ll start taking a look at PL\/pgSQL.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is part two of the little series about server side programming in PostgreSQL. In the last post we had a look at the basics when it comes to SQL functions. We learned how to write those functions, how we can pass parameters to functions, how to name parameters for better readability, how to return [&hellip;]<\/p>\n","protected":false},"author":29,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[229],"tags":[77],"type_dbi":[],"class_list":["post-15601","post","type-post","status-publish","format-standard","hentry","category-database-administration-monitoring","tag-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.2 (Yoast SEO v27.2) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types\" \/>\n<meta property=\"og:description\" content=\"This is part two of the little series about server side programming in PostgreSQL. In the last post we had a look at the basics when it comes to SQL functions. We learned how to write those functions, how we can pass parameters to functions, how to name parameters for better readability, how to return [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-02-07T13:10:37+00:00\" \/>\n<meta name=\"author\" content=\"Daniel Westermann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@westermanndanie\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Daniel Westermann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\"},\"author\":{\"name\":\"Daniel Westermann\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"headline\":\"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types\",\"datePublished\":\"2021-02-07T13:10:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\"},\"wordCount\":533,\"commentCount\":0,\"keywords\":[\"PostgreSQL\"],\"articleSection\":[\"Database Administration &amp; Monitoring\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\",\"name\":\"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\"},\"datePublished\":\"2021-02-07T13:10:37+00:00\",\"author\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.dbi-services.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#website\",\"url\":\"https:\/\/www.dbi-services.com\/blog\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66\",\"name\":\"Daniel Westermann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g\",\"caption\":\"Daniel Westermann\"},\"description\":\"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.\",\"sameAs\":[\"https:\/\/x.com\/westermanndanie\"],\"url\":\"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/","og_locale":"en_US","og_type":"article","og_title":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types","og_description":"This is part two of the little series about server side programming in PostgreSQL. In the last post we had a look at the basics when it comes to SQL functions. We learned how to write those functions, how we can pass parameters to functions, how to name parameters for better readability, how to return [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/","og_site_name":"dbi Blog","article_published_time":"2021-02-07T13:10:37+00:00","author":"Daniel Westermann","twitter_card":"summary_large_image","twitter_creator":"@westermanndanie","twitter_misc":{"Written by":"Daniel Westermann","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/"},"author":{"name":"Daniel Westermann","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"headline":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types","datePublished":"2021-02-07T13:10:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/"},"wordCount":533,"commentCount":0,"keywords":["PostgreSQL"],"articleSection":["Database Administration &amp; Monitoring"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/","url":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/","name":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"datePublished":"2021-02-07T13:10:37+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/an-introduction-into-server-side-programming-in-postgresql-2-sql-functions-sets-udts-and-polymorphic-types\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"An introduction into server side programming in PostgreSQL \u2013 2 \u2013 SQL functions, sets, udts and polymorphic types"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/8d08e9bd996a89bd75c0286cbabf3c66","name":"Daniel Westermann","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/31350ceeecb1dd8986339a29bf040d4cd3cd087d410deccd8f55234466d6c317?s=96&d=mm&r=g","caption":"Daniel Westermann"},"description":"Daniel Westermann is Principal Consultant and Technology Leader Open Infrastructure at dbi services. He has more than 15 years of experience in management, engineering and optimization of databases and infrastructures, especially on Oracle and PostgreSQL. Since the beginning of his career, he has specialized in Oracle Technologies and is Oracle Certified Professional 12c and Oracle Certified Expert RAC\/GridInfra. Over time, Daniel has become increasingly interested in open source technologies, becoming \u201cTechnology Leader Open Infrastructure\u201d and PostgreSQL expert. \u00a0Based on community or EnterpriseDB tools, he develops and installs complex high available solutions with PostgreSQL. He is also a certified PostgreSQL Plus 9.0 Professional and a Postgres Advanced Server 9.4 Professional. He is a regular speaker at PostgreSQL conferences in Switzerland and Europe. Today Daniel is also supporting our customers on AWS services such as AWS RDS, database migrations into the cloud, EC2 and automated infrastructure management with AWS SSM (System Manager). He is a certified AWS Solutions Architect Professional. Prior to dbi services, Daniel was Management System Engineer at LC SYSTEMS-Engineering AG in Basel. Before that, he worked as Oracle Developper &amp;\u00a0Project Manager at Delta Energy Solutions AG in Basel (today Powel AG). Daniel holds a diploma in Business Informatics (DHBW, Germany). His branch-related experience mainly covers the pharma industry, the financial sector, energy, lottery and telecommunications.","sameAs":["https:\/\/x.com\/westermanndanie"],"url":"https:\/\/www.dbi-services.com\/blog\/author\/daniel-westermann\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/15601","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/29"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=15601"}],"version-history":[{"count":0,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/15601\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=15601"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=15601"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=15601"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=15601"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}