<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>/devices/pseudo/bitbucket@0,0:pseudo (Posts about Data Engineering)</title><link>https://www.jmcpdotcom.com/blog/</link><description></description><atom:link href="https://www.jmcpdotcom.com/blog/categories/data-engineering.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2022 &lt;a href="mailto:blogadmin@jmcpdotcom.com"&gt;jmcp&lt;/a&gt; </copyright><lastBuildDate>Thu, 21 Apr 2022 02:58:35 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>I know, I'll use a regex!</title><link>https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/</link><dc:creator>jmcp</dc:creator><description>&lt;p&gt;This past week, a colleague asked me for help with a shell script that
he had come across while investigating how we run one of our data ingestion
pipelines. The shell script was designed to clean input CSV files if they
had lines which didn't match a specific pattern.&lt;/p&gt;
&lt;p&gt;Now to start with, the script was run over a directory and used a &lt;em&gt;very&lt;/em&gt;
gnarly bit of shell &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Glob_(programming)"&gt;globbing&lt;/a&gt;  to generate a list of files in a subdirectory.
That list was then iterated over to check for a &lt;cite&gt;.csv&lt;/cite&gt; extension.&lt;/p&gt;
&lt;p&gt;[Please save your eye-rolls and "but couldn't they..." for later].&lt;/p&gt;
&lt;p&gt;Once that list of files had been weeded to only contain CSVs, each of those
files was catted and read line by line to see if the line matched a desired
pattern - using shell regular expression parsing. If the line did not match
the pattern, it was deleted. The matching lines were then written to a new
file.&lt;/p&gt;
&lt;p&gt;[Again, please save your eye-rolls and "but couldn't they..." for later].&lt;/p&gt;
&lt;p&gt;The klaxons went off for my colleague when he saw the regex:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-1" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;NEW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="p"&gt;%.csv&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_clean.csv&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-2" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-2"&gt;&lt;/a&gt;  &lt;span class="o"&gt;{&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-3" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-3"&gt;&lt;/a&gt;  &lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-4" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-4"&gt;&lt;/a&gt;  &lt;span class="nb"&gt;read&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-5" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-5"&gt;&lt;/a&gt;  &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nv"&gt;IFS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nb"&gt;read&lt;/span&gt; -r line &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; -n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$line&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-6" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-6"&gt;&lt;/a&gt;  &lt;span class="k"&gt;do&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-7" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-7"&gt;&lt;/a&gt;        &lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-8" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-8"&gt;&lt;/a&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;~ ^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]{&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;-&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-2&lt;span class="o"&gt;])&lt;/span&gt;-&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-2&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;01&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="o"&gt;[&lt;/span&gt;^,&lt;span class="o"&gt;]&lt;/span&gt;*,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,.*$ &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-9" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-9"&gt;&lt;/a&gt;        &lt;span class="k"&gt;then&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-10" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-10"&gt;&lt;/a&gt;              &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$buffer&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-11" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-11"&gt;&lt;/a&gt;              &lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-12" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-12"&gt;&lt;/a&gt;        &lt;span class="k"&gt;else&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-13" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-13"&gt;&lt;/a&gt;              &lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;buffer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; "&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-14" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-14"&gt;&lt;/a&gt;        &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-15" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-15"&gt;&lt;/a&gt;  &lt;span class="k"&gt;done&lt;/span&gt;
&lt;a id="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-16" name="rest_code_a42af1a719fb4516ae880c31ce5b7f7f-16"&gt;&lt;/a&gt;  &lt;span class="o"&gt;}&lt;/span&gt; &amp;lt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NEW&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;My eyes got whiplash. To make it easier to understand, let's put each element of
the pattern on a single line:&lt;/p&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-1" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-1"&gt;&lt;/a&gt; ^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]{&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;-&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-2&lt;span class="o"&gt;])&lt;/span&gt;-&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-2&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;-9&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="m"&gt;01&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-2" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-2"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-3" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-3"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-4" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-4"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-5" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-5"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-6" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-6"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-7" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-7"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-8" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-8"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-9" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-9"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-10" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-10"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-11" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-11"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-12" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-12"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-13" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-13"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-14" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-14"&gt;&lt;/a&gt; &lt;span class="o"&gt;[&lt;/span&gt;^,&lt;span class="o"&gt;]&lt;/span&gt;*,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-15" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-15"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-16" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-16"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-17" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-17"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-18" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-18"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-19" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-19"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-20"&gt;&lt;code data-line-number="20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-20" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-20"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-21"&gt;&lt;code data-line-number="21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-21" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-21"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-22"&gt;&lt;code data-line-number="22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-22" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-22"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-23"&gt;&lt;code data-line-number="23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-23" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-23"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-24"&gt;&lt;code data-line-number="24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-24" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-24"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-25"&gt;&lt;code data-line-number="25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-25" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-25"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-26"&gt;&lt;code data-line-number="26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-26" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-26"&gt;&lt;/a&gt; &lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;^&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;*&lt;span class="se"&gt;\"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/#rest_code_a2c8b959f269425d95ab26eb16c2e463-27"&gt;&lt;code data-line-number="27"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;a id="rest_code_a2c8b959f269425d95ab26eb16c2e463-27" name="rest_code_a2c8b959f269425d95ab26eb16c2e463-27"&gt;&lt;/a&gt; .*$
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;Which is really something. The first field matches a date format - "yyyy-mm-dd"
(which is ok), then we have 12 fields where we care that they are enclosed in
double quotes, one field that we want to &lt;em&gt;not&lt;/em&gt; be quoted, another 12 fields
which are quoted again, and any other fields we don't care about.&lt;/p&gt;
&lt;p&gt;Wow.&lt;/p&gt;
&lt;p&gt;I told my colleague that this wasn't a good way of doing things (he agreed).&lt;/p&gt;
&lt;p&gt;There are better ways to achieve this, so let's walk through them.&lt;/p&gt;
&lt;p&gt;Firstly, the shell globbing. There's a Unix command to generate a list of
filesystem entries which match particular criteria. It's called &lt;a class="reference external" href="https://www.gnu.org/software/findutils/manual/html_mono/find.html"&gt;find&lt;/a&gt;. If
we want a list of files which have a 'csv' extension we do this:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_2db4cc40a0ac43b89f513f220e3f20aa-1" name="rest_code_2db4cc40a0ac43b89f513f220e3f20aa-1"&gt;&lt;/a&gt;$ find DIR -type f -name &lt;span class="se"&gt;\*&lt;/span&gt;.csv
&lt;/pre&gt;&lt;p&gt;You can use '.' or '*' or any way of representing a DIRectory in the filesystem.&lt;/p&gt;
&lt;p&gt;Now since we want this in a list to iterate over, let's put it in a variable:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_9e14475bec5642209b963aecbcd59b2e-1" name="rest_code_9e14475bec5642209b963aecbcd59b2e-1"&gt;&lt;/a&gt;$ &lt;span class="nv"&gt;CSVfiles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; find DIR -type f -name &lt;span class="se"&gt;\*&lt;/span&gt;.csv -o -name &lt;span class="se"&gt;\*&lt;/span&gt;.CSV &lt;span class="k"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;(You can redirect stderr to /dev/null, with &lt;em&gt;2&amp;gt;/dev/null&lt;/em&gt; inside the parens if you'd like).&lt;/p&gt;
&lt;p&gt;Now that we've got our list, we can move to the second phase - removing lines
which do not match our pattern. Let's try this first with &lt;a class="reference external" href="https://www.gnu.org/software/gawk"&gt;awk&lt;/a&gt;. Awk has
the concept of a &lt;a class="reference external" href="https://www.gnu.org/software/gawk/manual/gawk.html#Field-Separators"&gt;Field Separator&lt;/a&gt;, and since CSV files are Comma-&lt;em&gt;Separated&lt;/em&gt;-Value
files, let's make use of that feature. We also know that we are only really interested
in two fields - the first (yyyy-mm-dd) and the fourteenth.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_6653f13ddc394679b71007bf043b5abf-1" name="rest_code_6653f13ddc394679b71007bf043b5abf-1"&gt;&lt;/a&gt;$ awk -F&lt;span class="s1"&gt;','&lt;/span&gt; &lt;span class="s1"&gt;'$1 ~ /"[0-9]{4}-([0][0-9]|1[0-2])-([0-2][0-9]|3[01])"/ &amp;amp;&amp;amp;&lt;/span&gt;
&lt;a id="rest_code_6653f13ddc394679b71007bf043b5abf-2" name="rest_code_6653f13ddc394679b71007bf043b5abf-2"&gt;&lt;/a&gt;&lt;span class="s1"&gt;    $14 !~ /".*"/ {print}'&lt;/span&gt; &amp;lt; &lt;span class="nv"&gt;$old&lt;/span&gt; &amp;gt; &lt;span class="nv"&gt;$new&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;That's still rather ugly but considerably easier to read. For the record,
the bare ~ is awk's equals operator, and !~ is not-equals.&lt;/p&gt;
&lt;p&gt;We could also do this with &lt;a class="reference external" href="https://www.gnu.org/software/grep/manual/grep.html"&gt;grep&lt;/a&gt;, but at the cost of using more of that horrible regex.&lt;/p&gt;
&lt;p&gt;In my opinion a better method is to cons up a Python script for this validation
purpose, and we don't need to use the &lt;a class="reference external" href="https://docs.python.org/3.8/library/csv.html"&gt;CSV&lt;/a&gt; module.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-1" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-1"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;UserString&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-2" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-2"&gt;&lt;/a&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-3" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-3"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-4" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;infile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/path/to/file.csv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"rw"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-5" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-5"&gt;&lt;/a&gt;&lt;span class="nb"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-6" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-6"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-7" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-7"&gt;&lt;/a&gt;&lt;span class="n"&gt;linecount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-8" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-8"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-9" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-9"&gt;&lt;/a&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-10" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-10"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-11" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-11"&gt;&lt;/a&gt;    &lt;span class="n"&gt;fields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;","&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-12" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-12"&gt;&lt;/a&gt;    &lt;span class="n"&gt;togo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-13" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-13"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-14" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-14"&gt;&lt;/a&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-15" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-15"&gt;&lt;/a&gt;        &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strptime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s2"&gt;"%Y-%m-&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-16" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-16"&gt;&lt;/a&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;ValueError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_ve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-17" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-17"&gt;&lt;/a&gt;        &lt;span class="n"&gt;togo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-18" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-18"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-19" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-19"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;'"'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;UserString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isnumeric&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-20" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-20"&gt;&lt;/a&gt;        &lt;span class="n"&gt;togo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-21" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-21"&gt;&lt;/a&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;togo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-22" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-22"&gt;&lt;/a&gt;        &lt;span class="k"&gt;del&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-23" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-23"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-24" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-24"&gt;&lt;/a&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;linecount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-25" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-25"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# We've modified the input, so have to write out a new version, but&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-26" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-26"&gt;&lt;/a&gt;    &lt;span class="c1"&gt;# let's overwrite our input file rather than creating a new instance.&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-27" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-27"&gt;&lt;/a&gt;    &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-28" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-28"&gt;&lt;/a&gt;    &lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-29" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-29"&gt;&lt;/a&gt;
&lt;a id="rest_code_3b1a2a15c3004168a8e590e47adf46fe-30" name="rest_code_3b1a2a15c3004168a8e590e47adf46fe-30"&gt;&lt;/a&gt;&lt;span class="n"&gt;infile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;This script is pretty close to how I would write it in C (could you tell?).&lt;/p&gt;
&lt;p&gt;We first open the file (for reading &lt;em&gt;and&lt;/em&gt; writing) and read in every line,
which yields us a list. While it's not the most memory-efficient way of
approaching this problem, it does make processing more efficient because
it's one &lt;cite&gt;read()&lt;/cite&gt;, rather than one-read-per-line. We store the number of lines
that we've read in for comparison at the end of our loop, and then start the
processing.&lt;/p&gt;
&lt;p&gt;Since this is a &lt;a class="reference external" href="https://docs.python.org/3.8/library/csv.html"&gt;CSV&lt;/a&gt; file we know we can &lt;cite&gt;split()&lt;/cite&gt; on the comma, and having
done so, we check that we can parse the first field. We're not assigning to
a variable with &lt;cite&gt;datetime.strptime()&lt;/cite&gt; because we only care that we &lt;em&gt;can&lt;/em&gt;
rather than what the object's value is. The second check is to see that
we cannot find the double apostrophe in the element, and that the content of
the field is in fact numeric. If neither of these checks succeed, we know to
delete the line from our input.&lt;/p&gt;
&lt;p&gt;Finally, if we have in fact had to delete any lines, we rewind our file
(I was going to write pointer, but it's a File object. Told you it was close
to C!) to the start, and write out each line of input with a newline character
before closing the file.&lt;/p&gt;
&lt;p&gt;Whenever I think about regexes, &lt;em&gt;especially&lt;/em&gt; the ones I've written in C
over the years, I think about this quote which &lt;a class="reference external" href="http://regex.info/blog/2006-09-15/247"&gt;Jeffrey Friedl&lt;/a&gt; wrote about
a long time ago:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Some people, when confronted with a problem, think
“I know, I'll use regular expressions.”   Now they have two problems.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It was true when I first heard it some time during my first year of uni, and
still true today.&lt;/p&gt;
&lt;!-- put references after this point --&gt;</description><category>awk</category><category>data cleaning</category><category>Data Engineering</category><category>grep</category><category>programming</category><category>regex</category><category>regexes</category><category>regexp</category><category>regular expressions</category><category>sed</category><category>software engineering</category><category>SQL</category><guid>https://www.jmcpdotcom.com/blog/posts/2020-08-08-i-know-ill-use-a-regex/</guid><pubDate>Fri, 07 Aug 2020 16:00:00 GMT</pubDate></item><item><title>Common Table Expressions and an ORM</title><link>https://www.jmcpdotcom.com/blog/posts/2020-07-23-common-table-expressions-and-an-orm/</link><dc:creator>jmcp</dc:creator><description>&lt;p&gt;I solved a gnarly performance problem last week and I'd like to share with you what I learnt while
doing it.&lt;/p&gt;
&lt;p&gt;We received an alert from one of our automated monitoring systems that a particular query being
run via an API was taking too long. And by "too long" I mean &lt;em&gt;minutes&lt;/em&gt;. Since database engines
are optimised to return data to you in milliseconds, this seemed wildly wrong.&lt;/p&gt;
&lt;p&gt;The first step when you are checking a query for performance is to use the query analyzer. This is
a very powerful tool in any database, and helps you see just what the engine is going to do for any
particular bit of SQL. The term you're looking for in the documentation is &lt;a class="reference external" href="https://www.postgresql.org/docs/12/sql-explain.html"&gt;EXPLAIN&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We thought the query was fairly simple. It followed this general form:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_47cfdcbe281a4f869e9928b476042fe6-1" name="rest_code_47cfdcbe281a4f869e9928b476042fe6-1"&gt;&lt;/a&gt;SELECT columns, COUNT&lt;span class="o"&gt;(&lt;/span&gt;SELECT specific column WHERE conditions&lt;span class="o"&gt;)&lt;/span&gt;,
&lt;a id="rest_code_47cfdcbe281a4f869e9928b476042fe6-2" name="rest_code_47cfdcbe281a4f869e9928b476042fe6-2"&gt;&lt;/a&gt;FROM database
&lt;a id="rest_code_47cfdcbe281a4f869e9928b476042fe6-3" name="rest_code_47cfdcbe281a4f869e9928b476042fe6-3"&gt;&lt;/a&gt;WHERE conditions
&lt;a id="rest_code_47cfdcbe281a4f869e9928b476042fe6-4" name="rest_code_47cfdcbe281a4f869e9928b476042fe6-4"&gt;&lt;/a&gt;ORDER BY ordering criteria&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;and gave us not just results with specific conditions, but the count of rows which met those
conditions too.&lt;/p&gt;
&lt;p&gt;You will notice that I did not use &lt;em&gt;first set of conditions&lt;/em&gt; and &lt;em&gt;second set of conditions&lt;/em&gt;. This
is because the selection criteria were in fact the same. That was the first clue.&lt;/p&gt;
&lt;p&gt;A second clue was that of these selection conditions was that we had a range check - is the column's
value between A and B? [We actually had two, but having just one was sufficient to show the problem].
This was expressed as&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_8b843337b906468f9613443ace449c91-1" name="rest_code_8b843337b906468f9613443ace449c91-1"&gt;&lt;/a&gt;columnA &amp;gt;&lt;span class="o"&gt;=&lt;/span&gt; smallervalue AND
&lt;a id="rest_code_8b843337b906468f9613443ace449c91-2" name="rest_code_8b843337b906468f9613443ace449c91-2"&gt;&lt;/a&gt;columnA &amp;lt;&lt;span class="o"&gt;=&lt;/span&gt; largervalue
&lt;/pre&gt;&lt;p&gt;So you'll see that for each row we had two comparisons to do. I tried making that condition singular,
by using just &lt;em&gt;&amp;gt;= smallervalue&lt;/em&gt; (I also tried &lt;em&gt;&amp;lt;= largervalue&lt;/em&gt;&amp;gt; - no difference in timing) and while
that did make the query faster, it did not reflect what we need to be able to do, so that was out.&lt;/p&gt;
&lt;p&gt;Back to the query planner. It wasn't happy. It turns out that the most efficient plan it could come up
with was using a &lt;em&gt;Bitmap Index Scan&lt;/em&gt;. Twice. For the same query - but throwing the results of the first
query away before running the whole thing again.&lt;/p&gt;
&lt;p&gt;I knew that there had to be a better way (tm) - and there was. Here's the first thing I learned: the
SQL standard has a thing called a &lt;a class="reference external" href="https://www.postgresql.org/docs/12/queries-with.html"&gt;Common Table Expression&lt;/a&gt; or &lt;strong&gt;CTE&lt;/strong&gt;. This is a way of creating a
temporary table that is used for just that query.&lt;/p&gt;
&lt;p&gt;With this knowledge, I could now re-write the query in a considerably more efficient fashion. (It took
me several days to figure this out - I'm no SQL guru!)&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-1" name="rest_code_e90485881a7d4a5192dbc863799ace31-1"&gt;&lt;/a&gt;WITH better_query AS
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-2" name="rest_code_e90485881a7d4a5192dbc863799ace31-2"&gt;&lt;/a&gt;    &lt;span class="o"&gt;(&lt;/span&gt;SELECT columnname
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-3" name="rest_code_e90485881a7d4a5192dbc863799ace31-3"&gt;&lt;/a&gt;    FROM tablename
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-4" name="rest_code_e90485881a7d4a5192dbc863799ace31-4"&gt;&lt;/a&gt;    WHERE conditions&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-5" name="rest_code_e90485881a7d4a5192dbc863799ace31-5"&gt;&lt;/a&gt;SELECT columns, count&lt;span class="o"&gt;(&lt;/span&gt;better_query.columnname&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-6" name="rest_code_e90485881a7d4a5192dbc863799ace31-6"&gt;&lt;/a&gt;FROM tablename
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-7" name="rest_code_e90485881a7d4a5192dbc863799ace31-7"&gt;&lt;/a&gt;GROUP BY grouping criteria
&lt;a id="rest_code_e90485881a7d4a5192dbc863799ace31-8" name="rest_code_e90485881a7d4a5192dbc863799ace31-8"&gt;&lt;/a&gt;ORDER BY ordering criteria&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Excellent! ... except that that was giving me all the rows in &lt;cite&gt;tablename&lt;/cite&gt; which matched from &lt;cite&gt;better_query&lt;/cite&gt;
rather than the specific rows which met &lt;cite&gt;conditions&lt;/cite&gt;. To solve this niggle I needed a join.&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-1" name="rest_code_30c9832ddbaa41dfb81541a18935a673-1"&gt;&lt;/a&gt;WITH better_query AS
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-2" name="rest_code_30c9832ddbaa41dfb81541a18935a673-2"&gt;&lt;/a&gt;    &lt;span class="o"&gt;(&lt;/span&gt;SELECT columnname
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-3" name="rest_code_30c9832ddbaa41dfb81541a18935a673-3"&gt;&lt;/a&gt;    FROM tablename
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-4" name="rest_code_30c9832ddbaa41dfb81541a18935a673-4"&gt;&lt;/a&gt;    WHERE conditions&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-5" name="rest_code_30c9832ddbaa41dfb81541a18935a673-5"&gt;&lt;/a&gt;SELECT columns, count&lt;span class="o"&gt;(&lt;/span&gt;better_query.columnname&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-6" name="rest_code_30c9832ddbaa41dfb81541a18935a673-6"&gt;&lt;/a&gt;FROM tablename TN
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-7" name="rest_code_30c9832ddbaa41dfb81541a18935a673-7"&gt;&lt;/a&gt;JOIN better_query BQ on BQ.columnname &lt;span class="o"&gt;=&lt;/span&gt; TN.columnname
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-8" name="rest_code_30c9832ddbaa41dfb81541a18935a673-8"&gt;&lt;/a&gt;GROUP BY grouping criteria
&lt;a id="rest_code_30c9832ddbaa41dfb81541a18935a673-9" name="rest_code_30c9832ddbaa41dfb81541a18935a673-9"&gt;&lt;/a&gt;ORDER BY ordering criteria&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The query planner was a lot happier. Happier to the tune of a 20x improvement.&lt;/p&gt;
&lt;p&gt;There might have been a cheer or two.&lt;/p&gt;
&lt;p&gt;So how do we put this into our application codebase?&lt;/p&gt;
&lt;p&gt;While a major reason $employer hired me was my &lt;a class="reference external" href="https://www.python.org"&gt;Python&lt;/a&gt; skills, $employer isn't a Python shop
by any stretch of the imagination. We're a &lt;a class="reference external" href="https://adoptopenjdk.net/"&gt;Java&lt;/a&gt; shop, and I'm cross-pollinating :-).&lt;/p&gt;
&lt;p&gt;Part of that process has been learning how we abstract database specificities out of the code - we use an
&lt;a class="reference external" href="https://en.m.wikipedia.org/wiki/Object-relational_mapping"&gt;Object-Relational Mapping&lt;/a&gt; (aka ORM) to cope with using more than one vendor's database. There
are a few options for &lt;a class="reference external" href="https://en.m.wikipedia.org/wiki/List_of_object-relational_mapping_software#Java"&gt;Java ORMs&lt;/a&gt; and the one that we use is &lt;a class="reference external" href="https://www.jooq.org/"&gt;jOOQ&lt;/a&gt;. This is the first time
I've used an ORM (of course I've read about them, but years ago) so this too was something new
that I've learned. Heading to the documentation I read a lot, getting my head around the concepts
and syntax.&lt;/p&gt;
&lt;p&gt;It took me several days of research and hacking (&lt;a class="reference external" href="https://stackoverflow.com"&gt;stackoverflow&lt;/a&gt;, &lt;a class="reference external" href="https://github.com"&gt;github&lt;/a&gt;, come on down!) to work
out the correct syntax.&lt;/p&gt;
&lt;p&gt;Here's the gist of what we needed:&lt;/p&gt;
&lt;pre class="code java"&gt;&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-1" name="rest_code_9ad58bb211454a28804d99093095bd9d-1"&gt;&lt;/a&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;QueryClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-2" name="rest_code_9ad58bb211454a28804d99093095bd9d-2"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-3" name="rest_code_9ad58bb211454a28804d99093095bd9d-3"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;withClauseName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"betterQuery"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-4" name="rest_code_9ad58bb211454a28804d99093095bd9d-4"&gt;&lt;/a&gt;    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;withClauseField&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fieldName"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-5" name="rest_code_9ad58bb211454a28804d99093095bd9d-5"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-6" name="rest_code_9ad58bb211454a28804d99093095bd9d-6"&gt;&lt;/a&gt;    &lt;span class="p"&gt;....&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-7" name="rest_code_9ad58bb211454a28804d99093095bd9d-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-8" name="rest_code_9ad58bb211454a28804d99093095bd9d-8"&gt;&lt;/a&gt;    &lt;span class="n"&gt;CommonTableExpression&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Record1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;withClause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DSL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClauseName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-9" name="rest_code_9ad58bb211454a28804d99093095bd9d-9"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClauseField&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-10" name="rest_code_9ad58bb211454a28804d99093095bd9d-10"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columnName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-11" name="rest_code_9ad58bb211454a28804d99093095bd9d-11"&gt;&lt;/a&gt;            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-12" name="rest_code_9ad58bb211454a28804d99093095bd9d-12"&gt;&lt;/a&gt;            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-13" name="rest_code_9ad58bb211454a28804d99093095bd9d-13"&gt;&lt;/a&gt;        &lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-14" name="rest_code_9ad58bb211454a28804d99093095bd9d-14"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-15" name="rest_code_9ad58bb211454a28804d99093095bd9d-15"&gt;&lt;/a&gt;    &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DSL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-16" name="rest_code_9ad58bb211454a28804d99093095bd9d-16"&gt;&lt;/a&gt;        &lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DSL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columnName&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-17" name="rest_code_9ad58bb211454a28804d99093095bd9d-17"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-18" name="rest_code_9ad58bb211454a28804d99093095bd9d-18"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-19" name="rest_code_9ad58bb211454a28804d99093095bd9d-19"&gt;&lt;/a&gt;    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-20" name="rest_code_9ad58bb211454a28804d99093095bd9d-20"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-21" name="rest_code_9ad58bb211454a28804d99093095bd9d-21"&gt;&lt;/a&gt;    &lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-22" name="rest_code_9ad58bb211454a28804d99093095bd9d-22"&gt;&lt;/a&gt;&lt;span class="cm"&gt;     * append results field to array of column names in the select, then ...&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-23" name="rest_code_9ad58bb211454a28804d99093095bd9d-23"&gt;&lt;/a&gt;&lt;span class="cm"&gt;     */&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-24" name="rest_code_9ad58bb211454a28804d99093095bd9d-24"&gt;&lt;/a&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-25" name="rest_code_9ad58bb211454a28804d99093095bd9d-25"&gt;&lt;/a&gt;    &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Typename&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resultSet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DSLcontext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-26" name="rest_code_9ad58bb211454a28804d99093095bd9d-26"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-27" name="rest_code_9ad58bb211454a28804d99093095bd9d-27"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-28" name="rest_code_9ad58bb211454a28804d99093095bd9d-28"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-29" name="rest_code_9ad58bb211454a28804d99093095bd9d-29"&gt;&lt;/a&gt;            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;withClauseField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-30" name="rest_code_9ad58bb211454a28804d99093095bd9d-30"&gt;&lt;/a&gt;                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tablename&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;columnName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-31" name="rest_code_9ad58bb211454a28804d99093095bd9d-31"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columnName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-32" name="rest_code_9ad58bb211454a28804d99093095bd9d-32"&gt;&lt;/a&gt;        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columnName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-33" name="rest_code_9ad58bb211454a28804d99093095bd9d-33"&gt;&lt;/a&gt;    &lt;span class="p"&gt;....&lt;/span&gt;
&lt;a id="rest_code_9ad58bb211454a28804d99093095bd9d-34" name="rest_code_9ad58bb211454a28804d99093095bd9d-34"&gt;&lt;/a&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;No, it's not simple - but using &lt;a class="reference external" href="https://www.jooq.org/"&gt;jOOQ&lt;/a&gt; does mean that we can keep our code pretty close
to how we would write bare SQL (in this case that would still be rather gnarly), and that
is definitely a win.&lt;/p&gt;
&lt;section id="acknowledgement"&gt;
&lt;h2&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;Since this is another SQL-based post, I'd like to acknowledge the massive knowledge and
confidence boost I got from reading &lt;a class="reference external" href="https://twitter.com/b0rk"&gt;Julia Evans&lt;/a&gt; (aka &lt;a class="reference external" href="https://twitter.com/b0rk"&gt;b0rk&lt;/a&gt;)'s SQL zine &lt;a class="reference external" href="https://wizardzines.com/zines/sql/"&gt;Become a SELECT star&lt;/a&gt;.
She has a beautiful style and breaks complex technical concepts down into easily understandable
chunks with great illustrations. Reading that zine advanced my database confidence immensely.&lt;/p&gt;
&lt;!-- put references after this point --&gt;
&lt;/section&gt;</description><category>Data Engineering</category><category>Data Investigation</category><category>Database</category><category>Databases</category><category>Java</category><category>jOOQ software engineering</category><category>Oracle</category><category>ORM</category><category>PostgreSQL</category><category>programming</category><category>SQL</category><guid>https://www.jmcpdotcom.com/blog/posts/2020-07-23-common-table-expressions-and-an-orm/</guid><pubDate>Wed, 22 Jul 2020 11:00:00 GMT</pubDate></item><item><title>A brief introduction to the Python Database API</title><link>https://www.jmcpdotcom.com/blog/posts/2020-06-03-a-brief-introduction-to-the-python-database-api/</link><dc:creator>jmcp</dc:creator><description>&lt;p&gt;As popular as NoSQL databases currently are, there is still an immense amount
of data in the world for which the relational database is still the most appropriate
way to store, access and manipulate it. For those of us who like to use &lt;a class="reference external" href="https://www.python.org"&gt;Python&lt;/a&gt;
rather than &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Java_Database_Connectivity"&gt;JDBC&lt;/a&gt;, we are fortunate to have bindings for the major databases
which implement the &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-0249/"&gt;Python Database API&lt;/a&gt;, aka &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-0249/"&gt;PEP249&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This standard is important because it allows you to write your application in a way
that promotes cross-platform (cross-database engine) portability. While you do still
need to be aware of differences between the databases (for example, Oracle's &lt;strong&gt;VARCHAR2&lt;/strong&gt;
vs PostgreSQL's &lt;strong&gt;VARCHAR&lt;/strong&gt;), the essential tasks that you need to accomplish when
making use of a database are abstracted from you.&lt;/p&gt;
&lt;p&gt;In this brief introduction I will show you how to install two popular Python database
binding packages, connect to a database and run queries.&lt;/p&gt;
&lt;section id="installing-the-bits-you-need"&gt;
&lt;h2&gt;Installing the bits you need&lt;/h2&gt;
&lt;p&gt;I assume that you've got &lt;a class="reference external" href="https://www.python.org"&gt;Python&lt;/a&gt; installed on your system already, and that the database
you want to connect to is set up and running. What you need now are the &lt;em&gt;bindings&lt;/em&gt; for
that particular database. For the &lt;a class="reference external" href="https://www.oracle.com/database/technologies"&gt;Oracle database&lt;/a&gt;, this is a package known as &lt;a class="reference external" href="https://oracle.github.io/python-cx_Oracle/"&gt;cx_Oracle&lt;/a&gt;.
For &lt;a class="reference external" href="https://www.postgresql.org"&gt;PostgreSQL&lt;/a&gt;, I suggest &lt;a class="reference external" href="https://www.psycopg.org/"&gt;psycopg2&lt;/a&gt; though there are other bindings available.&lt;/p&gt;
&lt;p&gt;You will &lt;strong&gt;definitely&lt;/strong&gt; need to install the pre-packaged database client libraries on your
host (or in your container) as well. For &lt;a class="reference external" href="https://www.oracle.com"&gt;Oracle&lt;/a&gt; look for your platform in the
&lt;a class="reference external" href="https://www.oracle.com/database/technologies/instant-client.html"&gt;Oracle Instant Client&lt;/a&gt; download pages, for &lt;a class="reference external" href="https://www.postgresql.org"&gt;PostgreSQL&lt;/a&gt; on linux you will need &lt;em&gt;libpq-dev&lt;/em&gt;
as supplied by your package manager. On MacOS, please find the appropriate option from
the &lt;a class="reference external" href="https://www.postgresql.org/download/macosx/"&gt;PostgreSQL MacOSX download page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After you've installed these pieces, you can then &lt;code class="docutils literal"&gt;pip install &lt;span class="pre"&gt;--user&lt;/span&gt; cx_Oracle&lt;/code&gt; or
&lt;code class="docutils literal"&gt;pip install &lt;span class="pre"&gt;--user&lt;/span&gt; psycopg2&lt;/code&gt;. My personal preference is to install bindings in a &lt;em&gt;venv&lt;/em&gt;.
For &lt;a class="reference external" href="https://www.oracle.com/solaris/solaris11/"&gt;Solaris 11&lt;/a&gt; you can get the &lt;a class="reference external" href="https://oracle.github.io/python-cx_Oracle/"&gt;cx_Oracle&lt;/a&gt; bits &lt;em&gt;as well as&lt;/em&gt; the &lt;a class="reference external" href="https://www.oracle.com/database/technologies/instant-client.html"&gt;Oracle Instant Client&lt;/a&gt;
by uttering &lt;code class="docutils literal"&gt;pkg install cx_Oracle&lt;/code&gt;. [On a personal note, I made that possible - see the
History tab on the &lt;a class="reference external" href="https://github.com/oracle/solaris-userland/commits/master/components/python/cx_oracle"&gt;Solaris Userland cx_Oracle github&lt;/a&gt;].&lt;/p&gt;
&lt;/section&gt;
&lt;section id="getting-a-connection-to-the-database"&gt;
&lt;h2&gt;Getting a connection to the database&lt;/h2&gt;
&lt;p&gt;Now that you have the correct packages installed, you can start investigating. The first
thing to do is start an interactive interpreter and import the modules you need:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_abfb6788c9434518a054bd547bdd02d2-1" name="rest_code_abfb6788c9434518a054bd547bdd02d2-1"&gt;&lt;/a&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;python3&lt;/span&gt;&lt;span class="mf"&gt;.8&lt;/span&gt;
&lt;a id="rest_code_abfb6788c9434518a054bd547bdd02d2-2" name="rest_code_abfb6788c9434518a054bd547bdd02d2-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cx_Oracle&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;(Note that unless you're using Solaris' pre-packaged version, you &lt;strong&gt;must&lt;/strong&gt; point LD_LIBRARY_PATH to where
the module can locate the Instant Client libraries, specifically &lt;cite&gt;libclntsh.so&lt;/cite&gt;)&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_16aa56354cc844bf90df47b8cb53e6cf-1" name="rest_code_16aa56354cc844bf90df47b8cb53e6cf-1"&gt;&lt;/a&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="mf"&gt;3.8&lt;/span&gt;
&lt;a id="rest_code_16aa56354cc844bf90df47b8cb53e6cf-2" name="rest_code_16aa56354cc844bf90df47b8cb53e6cf-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;psycopg2&lt;/span&gt;
&lt;a id="rest_code_16aa56354cc844bf90df47b8cb53e6cf-3" name="rest_code_16aa56354cc844bf90df47b8cb53e6cf-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;psycopg2.extras&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;execute_batch&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We need a connection to the database, which in Oracle terms is a DSN, or &lt;em&gt;Data Source Name&lt;/em&gt;.
This is made up of the username, password, host (either address or IP), port and database instance name.
Put together, the host, port and database instance are what Oracle calls the "service name".&lt;/p&gt;
&lt;p&gt;The common example you will see in Oracle documentation (and on &lt;a class="reference external" href="https://stackoverflow.com"&gt;stackoverflow&lt;/a&gt;!) is&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_869b5525b0cc4179ae908a0b8852d966-1" name="rest_code_869b5525b0cc4179ae908a0b8852d966-1"&gt;&lt;/a&gt;scott/tiger@orcl:1521/orcl
&lt;/pre&gt;&lt;p&gt;I'm a bit over seeing that, so I've created a different username and DBname:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_9b4f019440f848258a8d620dd01b7050-1" name="rest_code_9b4f019440f848258a8d620dd01b7050-1"&gt;&lt;/a&gt;DEMOUSER/DemoDbUser1@dbhost:1521/demodb
&lt;/pre&gt;&lt;p&gt;Since Oracle defaults to using port 1521 on the host, you only need to specify the port number if your
database is listening on a different port.&lt;/p&gt;
&lt;p&gt;An Oracle connection is therefore&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-1" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"DEMOUSER"&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-2" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-2"&gt;&lt;/a&gt;&lt;span class="n"&gt;passwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"DemoDbUser1"&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-3" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-3"&gt;&lt;/a&gt;&lt;span class="n"&gt;servicename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dbhost:1521/demodb"&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-4" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-5" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-6" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-6"&gt;&lt;/a&gt;    &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cx_Oracle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;servicename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-7" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-7"&gt;&lt;/a&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;cx_Oracle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DatabaseError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;dbe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-8" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-8"&gt;&lt;/a&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""Unable to obtain a connection to &lt;/span&gt;&lt;span class="si"&gt;{servicename}&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;servicename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;servicename&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_06ecf7f1fdb04d8280ae41469dea3270-9" name="rest_code_06ecf7f1fdb04d8280ae41469dea3270-9"&gt;&lt;/a&gt;    &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;With &lt;a class="reference external" href="https://www.postgresql.org"&gt;PostgreSQL&lt;/a&gt; we can also specify whether we want SSL enabled.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-1" name="rest_code_978c35b3b41c4f11b112b443de988cfc-1"&gt;&lt;/a&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-2" name="rest_code_978c35b3b41c4f11b112b443de988cfc-2"&gt;&lt;/a&gt;    &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbname&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-3" name="rest_code_978c35b3b41c4f11b112b443de988cfc-3"&gt;&lt;/a&gt;                                  &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbuser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-4" name="rest_code_978c35b3b41c4f11b112b443de988cfc-4"&gt;&lt;/a&gt;                                  &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbpassword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-5" name="rest_code_978c35b3b41c4f11b112b443de988cfc-5"&gt;&lt;/a&gt;                                  &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbhost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-6" name="rest_code_978c35b3b41c4f11b112b443de988cfc-6"&gt;&lt;/a&gt;                                  &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-7" name="rest_code_978c35b3b41c4f11b112b443de988cfc-7"&gt;&lt;/a&gt;                                  &lt;span class="n"&gt;sslmode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbsslmode&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-8" name="rest_code_978c35b3b41c4f11b112b443de988cfc-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;psycopg2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OperationalError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;dboe&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-9" name="rest_code_978c35b3b41c4f11b112b443de988cfc-9"&gt;&lt;/a&gt;    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""Unable to obtain a connection to the database.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-10" name="rest_code_978c35b3b41c4f11b112b443de988cfc-10"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          Please check your database connection details&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-11" name="rest_code_978c35b3b41c4f11b112b443de988cfc-11"&gt;&lt;/a&gt;&lt;span class="s2"&gt;          Notify dbadmin@&lt;/span&gt;&lt;span class="si"&gt;{dbhost}&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbhost&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbhost&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-12" name="rest_code_978c35b3b41c4f11b112b443de988cfc-12"&gt;&lt;/a&gt;          &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_978c35b3b41c4f11b112b443de988cfc-13" name="rest_code_978c35b3b41c4f11b112b443de988cfc-13"&gt;&lt;/a&gt;    &lt;span class="k"&gt;raise&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Once we have the connection, we need a cursor so we can execute statements:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_9c09af6825224ea09ecc582c2a544036-1" name="rest_code_9c09af6825224ea09ecc582c2a544036-1"&gt;&lt;/a&gt;&lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Now that we have our connection and a cursor to use, what can we do with it? SQL baby!&lt;/p&gt;
&lt;p&gt;We need a handy dataset to muck around with, so I've got just the thing courtesy of
my previous post about &lt;a class="reference external" href="https://www.jmcpdotcom.com/blog/posts/2019-09-27-microservices-part-1/"&gt;determining your electorate&lt;/a&gt;. My JSON files have a fairly
basic structure reflecting my needs for that project, but that is still sufficient
our purposes here.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-1" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-2" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;actf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"find-my-electorate/json/ACT.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-3" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;actf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-4" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-4"&gt;&lt;/a&gt;&lt;span class="n"&gt;dict_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'Brindabella'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ginninderra'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Kurrajong'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Murrumbidgee'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Yerrabi'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-5" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-5"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;actf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Yerrabi"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-6" name="rest_code_b87ce28d4dd04d2b9d61c1128d3dc3d7-6"&gt;&lt;/a&gt;&lt;span class="n"&gt;dict_keys&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'jurisdiction'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'locality'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'blocks'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'coords'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The 'jurisdiction' key is the state or territory name (ACT, Australian Capital Territory in this case),
the 'locality' is the electorate name, 'blocks' is a list of the  &lt;a class="reference external" href="https://www.abs.gov.au"&gt;Australian Bureau of Statistics&lt;/a&gt;
&lt;a class="reference external" href="https://en.wikipedia.org/wiki/Meshblock#Australia"&gt;Mesh Block&lt;/a&gt; which the electorate contains, and 'coords' is a list of the latitude, longitude pairs
which are the boundaries of those blocks.&lt;/p&gt;
&lt;p&gt;Now we need a schema to operate within. This is reasonably simple - if you've done any work with
SQL databases. To start with, we need two &lt;em&gt;SEQUENCE&lt;/em&gt; s, which are database objects from which
any database user may generate a unique integer. This is the easiest and cheapest way that I know
of to generate values for primary key columns. (For a good explanation on them, see the
&lt;a class="reference external" href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/CREATE-SEQUENCE.html#GUID-E9C78A8C-615A-4757-B2A8-5E6EFB130571"&gt;Oracle 19c CREATE SEQUENCE&lt;/a&gt; page). After that, we'll create two tables: electorate and geopoints.
(We're going to ignore the &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Meshblock#Australia"&gt;Mesh Block&lt;/a&gt; data, it's not useful for this example).&lt;/p&gt;
&lt;pre class="code SQL"&gt;&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-1" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;-- This is the Oracle DB form&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-2" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-2"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;GEOPOINTS&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINTS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-3" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-3"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINTS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-4" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-4"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-5" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-5"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATE_SEQ&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-6" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-6"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;LATLONG_SEQ&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-7" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-7"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-8" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-8"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATE_SEQ&lt;/span&gt; &lt;span class="k"&gt;INCREMENT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;MINVALUE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;NOMAXVALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-9" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-9"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;LATLONG_SEQ&lt;/span&gt; &lt;span class="k"&gt;INCREMENT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;MINVALUE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="n"&gt;NOMAXVALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-10" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-10"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-11" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-11"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-12" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-12"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE_PK&lt;/span&gt;   &lt;span class="nb"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;DEMOUSER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ELECTORATE_SEQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NEXTVAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-13" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-13"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE&lt;/span&gt;      &lt;span class="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-14" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-14"&gt;&lt;/a&gt;    &lt;span class="n"&gt;STATENAME&lt;/span&gt;       &lt;span class="n"&gt;VARCHAR2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="c1"&gt;-- Using the abbreviated form&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-15" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-15"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-16" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-16"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-17" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-17"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;GEOPOINTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-18" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-18"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LATLONG_PK&lt;/span&gt;      &lt;span class="nb"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;DEMOUSER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LATLONG_SEQ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NEXTVAL&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-19" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-19"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LATITUDE&lt;/span&gt;        &lt;span class="nb"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-20" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-20"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LONGITUDE&lt;/span&gt;       &lt;span class="nb"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-21" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-21"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE_FK&lt;/span&gt;   &lt;span class="nb"&gt;NUMBER&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ELECTORATE_PK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-22" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-22"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-23" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-23"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-24" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-24"&gt;&lt;/a&gt;&lt;span class="c1"&gt;-- Now for the PostgreSQL form&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-25" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-25"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="k"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;GEOPOINTS&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-26" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-26"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="k"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-27" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-27"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-28" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-28"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="k"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;ELECTORATE_SEQ&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-29" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-29"&gt;&lt;/a&gt;&lt;span class="k"&gt;DROP&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="k"&gt;IF&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="n"&gt;LATLONG_SEQ&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-30" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-30"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-31" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-31"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATE_SEQ&lt;/span&gt; &lt;span class="k"&gt;INCREMENT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;MINVALUE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;NO&lt;/span&gt; &lt;span class="k"&gt;MAXVALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-32" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-32"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;SEQUENCE&lt;/span&gt; &lt;span class="n"&gt;LATLONG_SEQ&lt;/span&gt; &lt;span class="k"&gt;INCREMENT&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;MINVALUE&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;NO&lt;/span&gt; &lt;span class="k"&gt;MAXVALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-33" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-33"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-34" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-34"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-35" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-35"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE_PK&lt;/span&gt;   &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NEXTVAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ELECTORATE_SEQ'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-36" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-36"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE&lt;/span&gt;      &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-37" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-37"&gt;&lt;/a&gt;    &lt;span class="n"&gt;STATENAME&lt;/span&gt;       &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="c1"&gt;-- Using the abbreviated form&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-38" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-38"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-39" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-39"&gt;&lt;/a&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-40" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-40"&gt;&lt;/a&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;GEOPOINTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-41" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-41"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LATLONG_PK&lt;/span&gt;      &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;DEFAULT&lt;/span&gt; &lt;span class="n"&gt;NEXTVAL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'LATLONG_SEQ'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-42" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-42"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LATITUDE&lt;/span&gt;        &lt;span class="nb"&gt;NUMERIC&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-43" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-43"&gt;&lt;/a&gt;    &lt;span class="n"&gt;LONGITUDE&lt;/span&gt;       &lt;span class="nb"&gt;NUMERIC&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-44" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-44"&gt;&lt;/a&gt;    &lt;span class="n"&gt;ELECTORATE_FK&lt;/span&gt;   &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;ELECTORATES&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ELECTORATE_PK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;a id="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-45" name="rest_code_c4f14f494c244b02bf719f5dbb0fa6b0-45"&gt;&lt;/a&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We need to execute these statements one by one, using &lt;cite&gt;cursor.execute()&lt;/cite&gt;. Come back once you've
done that and we've got our schema set up.&lt;/p&gt;
&lt;p&gt;[I see that a short time has passed - welcome back]&lt;/p&gt;
&lt;p&gt;Now we need to populate our database. For both connection types, we'll make use of prepared
statements, which allow us to insert, update, delete or select many rows at a time. For the
Oracle connection we'll use the &lt;cite&gt;executemany()&lt;/cite&gt; function, but for PostgreSQL's &lt;a class="reference external" href="https://www.psycopg.org/"&gt;psycopg2&lt;/a&gt;
bindings we'll use &lt;cite&gt;execute_batch()&lt;/cite&gt; instead. (See the &lt;a class="reference external" href="https://www.psycopg.org/docs/extras.html?highlight=prepared#fast-execution-helpers"&gt;psycopg2 website note&lt;/a&gt; about it).&lt;/p&gt;
&lt;p&gt;For the Oracle examples, we'll use a bind variable so that when we &lt;cite&gt;INSERT&lt;/cite&gt; into
the &lt;cite&gt;ELECTORATES&lt;/cite&gt; table we get the &lt;cite&gt;ELECTORATE_PK&lt;/cite&gt; to use in the subsequent &lt;cite&gt;INSERT&lt;/cite&gt; to the
&lt;cite&gt;GEOPOINTS&lt;/cite&gt; table. That saves us a query to get that information. The &lt;a class="reference external" href="https://www.psycopg.org/"&gt;psycopg2&lt;/a&gt; module
does not have this support, unfortunately. Since we have many records to process, I've created
some small functions to enable &lt;a class="reference external" href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself"&gt;DRY&lt;/a&gt;&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-1" name="rest_code_009e643fbf124a0886afb3bc2578cccc-1"&gt;&lt;/a&gt;&lt;span class="c1"&gt;# Oracle version&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-2" name="rest_code_009e643fbf124a0886afb3bc2578cccc-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;epk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-3" name="rest_code_009e643fbf124a0886afb3bc2578cccc-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;electStmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""INSERT INTO ELECTORATES (ELECTORATE, STATENAME)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-4" name="rest_code_009e643fbf124a0886afb3bc2578cccc-4"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                VALUES (:electorate, :statename)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-5" name="rest_code_009e643fbf124a0886afb3bc2578cccc-5"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                RETURNING ELECTORATE_PK INTO :epk"""&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-6" name="rest_code_009e643fbf124a0886afb3bc2578cccc-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;geoStmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""INSERT INTO GEOPOINTS(LATITUDE, LONGITUDE, ELECTORATE_FK)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-7" name="rest_code_009e643fbf124a0886afb3bc2578cccc-7"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...              VALUES (:lat, :long, :fk)"""&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-8" name="rest_code_009e643fbf124a0886afb3bc2578cccc-8"&gt;&lt;/a&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-9" name="rest_code_009e643fbf124a0886afb3bc2578cccc-9"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-10" name="rest_code_009e643fbf124a0886afb3bc2578cccc-10"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;electorate&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-11" name="rest_code_009e643fbf124a0886afb3bc2578cccc-11"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;edict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"electorate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"locality"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-12" name="rest_code_009e643fbf124a0886afb3bc2578cccc-12"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                  &lt;span class="s2"&gt;"statename"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"jurisdiction"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-13" name="rest_code_009e643fbf124a0886afb3bc2578cccc-13"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                  &lt;span class="s2"&gt;"epk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;epk&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-14" name="rest_code_009e643fbf124a0886afb3bc2578cccc-14"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;electStmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-15" name="rest_code_009e643fbf124a0886afb3bc2578cccc-15"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-16" name="rest_code_009e643fbf124a0886afb3bc2578cccc-16"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;latlong&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"coords"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-17" name="rest_code_009e643fbf124a0886afb3bc2578cccc-17"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latlong&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-18" name="rest_code_009e643fbf124a0886afb3bc2578cccc-18"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                            &lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latlong&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-19" name="rest_code_009e643fbf124a0886afb3bc2578cccc-19"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                            &lt;span class="s2"&gt;"fk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getvalue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])})&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-20" name="rest_code_009e643fbf124a0886afb3bc2578cccc-20"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;executemany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;geoStmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-21" name="rest_code_009e643fbf124a0886afb3bc2578cccc-21"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-22" name="rest_code_009e643fbf124a0886afb3bc2578cccc-22"&gt;&lt;/a&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-23" name="rest_code_009e643fbf124a0886afb3bc2578cccc-23"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;allpoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-24" name="rest_code_009e643fbf124a0886afb3bc2578cccc-24"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;states&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"act"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"nsw"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"nt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"qld"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"sa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"tas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"wa"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"vic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"federal"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-25" name="rest_code_009e643fbf124a0886afb3bc2578cccc-25"&gt;&lt;/a&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-26" name="rest_code_009e643fbf124a0886afb3bc2578cccc-26"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;states&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-27" name="rest_code_009e643fbf124a0886afb3bc2578cccc-27"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;allpoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"json/&lt;/span&gt;&lt;span class="si"&gt;{stu}&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_009e643fbf124a0886afb3bc2578cccc-28" name="rest_code_009e643fbf124a0886afb3bc2578cccc-28"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;addstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;allpoints&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;For the PostgreSQL version, we need to subtly change the &lt;cite&gt;INSERT&lt;/cite&gt; statements:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_a7737c2f0b754830bcd5a283a49c00e4-1" name="rest_code_a7737c2f0b754830bcd5a283a49c00e4-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;electStmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""INSERT INTO ELECTORATES (ELECTORATE, STATENAME)&lt;/span&gt;
&lt;a id="rest_code_a7737c2f0b754830bcd5a283a49c00e4-2" name="rest_code_a7737c2f0b754830bcd5a283a49c00e4-2"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                VALUES (&lt;/span&gt;&lt;span class="si"&gt;%(electorate)s&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%(statename)s&lt;/span&gt;&lt;span class="s2"&gt;)&lt;/span&gt;
&lt;a id="rest_code_a7737c2f0b754830bcd5a283a49c00e4-3" name="rest_code_a7737c2f0b754830bcd5a283a49c00e4-3"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                RETURNING ELECTORATE_PK"""&lt;/span&gt;
&lt;a id="rest_code_a7737c2f0b754830bcd5a283a49c00e4-4" name="rest_code_a7737c2f0b754830bcd5a283a49c00e4-4"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;geoStmt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""INSERT INTO GEOPOINTS(LATITUDE, LONGITUDE, ELECTORATE_FK)&lt;/span&gt;
&lt;a id="rest_code_a7737c2f0b754830bcd5a283a49c00e4-5" name="rest_code_a7737c2f0b754830bcd5a283a49c00e4-5"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                VALUES (&lt;/span&gt;&lt;span class="si"&gt;%(latitude)s&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%(longitude)s&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%(fk)s&lt;/span&gt;&lt;span class="s2"&gt;)"""&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Another thing we need to change is the first execute, because bind variables are an
Oracle extension, and we're also going to change from &lt;cite&gt;executemany()&lt;/cite&gt; to &lt;cite&gt;execute_batch()&lt;/cite&gt;:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-1" name="rest_code_60e897fb25464af4a7e2e8009e83600a-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addstate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-2" name="rest_code_60e897fb25464af4a7e2e8009e83600a-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;electorate&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-3" name="rest_code_60e897fb25464af4a7e2e8009e83600a-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;edict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"electorate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"locality"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-4" name="rest_code_60e897fb25464af4a7e2e8009e83600a-4"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                  &lt;span class="s2"&gt;"statename"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"jurisdiction"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-5" name="rest_code_60e897fb25464af4a7e2e8009e83600a-5"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;electStmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;edict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-6" name="rest_code_60e897fb25464af4a7e2e8009e83600a-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;epk&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-7" name="rest_code_60e897fb25464af4a7e2e8009e83600a-7"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-8" name="rest_code_60e897fb25464af4a7e2e8009e83600a-8"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;latlong&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;"coords"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-9" name="rest_code_60e897fb25464af4a7e2e8009e83600a-9"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;             &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"latitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latlong&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-10" name="rest_code_60e897fb25464af4a7e2e8009e83600a-10"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;                            &lt;span class="s2"&gt;"longitude"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latlong&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="s2"&gt;"fk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;epk&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-11" name="rest_code_60e897fb25464af4a7e2e8009e83600a-11"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;execute_batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;geoStmt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_60e897fb25464af4a7e2e8009e83600a-12" name="rest_code_60e897fb25464af4a7e2e8009e83600a-12"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;The rest of the data loading is the same as with Oracle. Since I'm curious about
efficiencies, I did a rough benchmark of the data load with &lt;cite&gt;executemany()&lt;/cite&gt;  as well,
and it was around half the speed of using &lt;cite&gt;execute_batch()&lt;/cite&gt;. YMMV, of course, so always
test your code with &lt;em&gt;your&lt;/em&gt; data and as close to real-world conditions as possible.&lt;/p&gt;
&lt;p&gt;Now that we have the data loaded we can do some investigations. I'm going to show the
PostgreSQL output for this and call out differences with Oracle where necessary.&lt;/p&gt;
&lt;p&gt;While some parts of our state and territory borders follow rivers and mountain ranges, quite a &lt;em&gt;lot&lt;/em&gt; of
them follow specific latitudes and longitudes. The border between Queensland and New South Wales, for
example is mostly along the 29th parallel. Between the Northern Territory and South Australia it's the
26th parallel, and that between South Australia and Western Australia is along meridian 129 East.&lt;/p&gt;
&lt;p&gt;If you go to a mapping service and plug in 29S,141E (the line between Queensland and New South Wales):&lt;/p&gt;
&lt;a class="reference external image-reference" href="https://www.google.com.au/maps/place/29%C2%B000'00.0%22S+141%C2%B000'00.0%22E/@-28.9999953,140.9978113,17z/data=!3m1!4b1!4m5!3m4!1s0x0:0x0!8m2!3d-29!4d141"&gt;&lt;img alt="/images/2020/python-db-api/29s141e-400x400.png" src="https://www.jmcpdotcom.com/blog/images/2020/python-db-api/29s141e-400x400.png"&gt;&lt;/a&gt;
&lt;p&gt;you'll see that the &lt;em&gt;exact&lt;/em&gt; point is not where the boundary is actually drawn. That means we need to use
some fuzziness in our matching.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-1" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""SELECT STATENAME, ELECTORATE FROM ELECTORATES E WHERE ELECTORATE_PK IN&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-2" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-2"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   (SELECT DISTINCT ELECTORATE_FK FROM GEOPOINTS WHERE LATITUDE BETWEEN -29.001 AND -28.995)&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-3" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-3"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   ORDER BY STATENAME, ELECTORATE"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-4" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-4"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-5" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-5"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-6" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{s:6}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{e}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-7" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-7"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-8" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-8"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Ballina&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-9" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-9"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Barwon&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-10" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-10"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Clarence&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-11" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-11"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Lismore&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-12" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-12"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;New&lt;/span&gt; &lt;span class="n"&gt;England&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-13" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-13"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Northern&lt;/span&gt; &lt;span class="n"&gt;Tablelands&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-14" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-14"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Page&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-15" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-15"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Parkes&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-16" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-16"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Maranoa&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-17" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-17"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Southern&lt;/span&gt; &lt;span class="n"&gt;Downs&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-18" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-18"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Warrego&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-19" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-19"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Giles&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-20" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-20"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Grey&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-21" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-21"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Stuart&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-22" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-22"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Stuart&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-23" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-23"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Durack&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-24" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-24"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Geraldton&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-25" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-25"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Kalgoorlie&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-26" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-26"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Moore&lt;/span&gt;
&lt;a id="rest_code_84f093f2bf88492eb64d8ea93fe64905-27" name="rest_code_84f093f2bf88492eb64d8ea93fe64905-27"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;North&lt;/span&gt; &lt;span class="n"&gt;West&lt;/span&gt; &lt;span class="n"&gt;Central&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Hmm. Not only did I not want SA or WA electorates returned, the database has also given me the &lt;em&gt;federal&lt;/em&gt; electorates as well.
Let's update our electorates table to reflect that jurisdictional issue:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_16e3b7661d3746409c3569db4be4cd98-1" name="rest_code_16e3b7661d3746409c3569db4be4cd98-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""ALTER TABLE ELECTORATES ADD FEDERAL BOOLEAN"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_16e3b7661d3746409c3569db4be4cd98-2" name="rest_code_16e3b7661d3746409c3569db4be4cd98-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Popping into a &lt;cite&gt;psql&lt;/cite&gt; session for a moment, let's see what we have:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-1" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;demodb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; &lt;span class="se"&gt;\d&lt;/span&gt; electorates
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-2" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-2"&gt;&lt;/a&gt;                                    Table &lt;span class="s2"&gt;"public.electorates"&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-3" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-3"&gt;&lt;/a&gt;    Column     &lt;span class="p"&gt;|&lt;/span&gt;         Type          &lt;span class="p"&gt;|&lt;/span&gt; Collation &lt;span class="p"&gt;|&lt;/span&gt; Nullable &lt;span class="p"&gt;|&lt;/span&gt;               Default
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-4" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-4"&gt;&lt;/a&gt;---------------+-----------------------+-----------+----------+-------------------------------------
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-5" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-5"&gt;&lt;/a&gt; electorate_pk &lt;span class="p"&gt;|&lt;/span&gt; integer               &lt;span class="p"&gt;|&lt;/span&gt;           &lt;span class="p"&gt;|&lt;/span&gt; not null &lt;span class="p"&gt;|&lt;/span&gt; nextval&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'electorate_seq'&lt;/span&gt;::regclass&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-6" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-6"&gt;&lt;/a&gt; electorate    &lt;span class="p"&gt;|&lt;/span&gt; character varying&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;           &lt;span class="p"&gt;|&lt;/span&gt; not null &lt;span class="p"&gt;|&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-7" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-7"&gt;&lt;/a&gt; statename     &lt;span class="p"&gt;|&lt;/span&gt; character varying&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;|&lt;/span&gt;           &lt;span class="p"&gt;|&lt;/span&gt; not null &lt;span class="p"&gt;|&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-8" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-8"&gt;&lt;/a&gt; federal       &lt;span class="p"&gt;|&lt;/span&gt; boolean               &lt;span class="p"&gt;|&lt;/span&gt;           &lt;span class="p"&gt;|&lt;/span&gt;          &lt;span class="p"&gt;|&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-9" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-9"&gt;&lt;/a&gt;Indexes:
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-10" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-10"&gt;&lt;/a&gt;    &lt;span class="s2"&gt;"electorates_pkey"&lt;/span&gt; PRIMARY KEY, btree &lt;span class="o"&gt;(&lt;/span&gt;electorate_pk&lt;span class="o"&gt;)&lt;/span&gt;
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-11" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-11"&gt;&lt;/a&gt;Referenced by:
&lt;a id="rest_code_e90cea1e2db14364b5c0b9ba665bf662-12" name="rest_code_e90cea1e2db14364b5c0b9ba665bf662-12"&gt;&lt;/a&gt;    TABLE &lt;span class="s2"&gt;"geopoints"&lt;/span&gt; CONSTRAINT &lt;span class="s2"&gt;"geopoints_electorate_fk_fkey"&lt;/span&gt; FOREIGN KEY &lt;span class="o"&gt;(&lt;/span&gt;electorate_fk&lt;span class="o"&gt;)&lt;/span&gt; REFERENCES electorates&lt;span class="o"&gt;(&lt;/span&gt;electorate_pk&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Now let's populate that column. Unfortunately, though, some state electorates have the same name as federal electorates - and
some electorate names exist in more than one state, too! (I'm looking at you, Bass!). Tempting as it is to zorch our db and
start from scratch, I'm going to take advantage of this information:&lt;/p&gt;
&lt;ol class="arabic simple"&gt;
&lt;li&gt;&lt;p&gt;We added the federal electorate list after all the states,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;the federal list was constructed starting with the ACT, and therefore&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Federal electorates will have a higher primary key value than all the states and territories.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With that in mind here's the first federal electorate entry:&lt;/p&gt;
&lt;pre class="code shell"&gt;&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-1" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-1"&gt;&lt;/a&gt;&lt;span class="nv"&gt;demodb&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;gt; SELECT ELECTORATE_PK, ELECTORATE, STATENAME FROM ELECTORATES WHERE &lt;span class="nv"&gt;STATENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ACT'&lt;/span&gt; ORDER BY ELECTORATE_PK, STATENAME&lt;span class="p"&gt;;&lt;/span&gt;
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-2" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-2"&gt;&lt;/a&gt; electorate_pk &lt;span class="p"&gt;|&lt;/span&gt;  electorate  &lt;span class="p"&gt;|&lt;/span&gt; statename
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-3" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-3"&gt;&lt;/a&gt;---------------+--------------+-----------
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-4" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-4"&gt;&lt;/a&gt;             &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Brindabella  &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-5" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-5"&gt;&lt;/a&gt;             &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Ginninderra  &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-6" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-6"&gt;&lt;/a&gt;             &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Kurrajong    &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-7" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-7"&gt;&lt;/a&gt;             &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Murrumbidgee &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-8" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-8"&gt;&lt;/a&gt;             &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Yerrabi      &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-9" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-9"&gt;&lt;/a&gt;           &lt;span class="m"&gt;416&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Bean         &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-10" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-10"&gt;&lt;/a&gt;           &lt;span class="m"&gt;417&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Canberra     &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-11" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-11"&gt;&lt;/a&gt;           &lt;span class="m"&gt;418&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; Fenner       &lt;span class="p"&gt;|&lt;/span&gt; ACT
&lt;a id="rest_code_92a473cd465f4548bfe84dfec6fe1a86-12" name="rest_code_92a473cd465f4548bfe84dfec6fe1a86-12"&gt;&lt;/a&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt; rows&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Let's check how many electorates have a primary key &lt;em&gt;higher&lt;/em&gt; than Bean:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_7670b2b022af4c27b07f4dad899d55d0-1" name="rest_code_7670b2b022af4c27b07f4dad899d55d0-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""SELECT COUNT(ELECTORATE_PK), MAX(ELECTORATE_PK) FROM ELECTORATES"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_7670b2b022af4c27b07f4dad899d55d0-2" name="rest_code_7670b2b022af4c27b07f4dad899d55d0-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_7670b2b022af4c27b07f4dad899d55d0-3" name="rest_code_7670b2b022af4c27b07f4dad899d55d0-3"&gt;&lt;/a&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;566&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;566&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;And a quick check to see that we do in fact have 151 electorates with that condition:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_b40e64c765a44f2abeedcd8693a9cdc0-1" name="rest_code_b40e64c765a44f2abeedcd8693a9cdc0-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;566&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;415&lt;/span&gt;
&lt;a id="rest_code_b40e64c765a44f2abeedcd8693a9cdc0-2" name="rest_code_b40e64c765a44f2abeedcd8693a9cdc0-2"&gt;&lt;/a&gt;&lt;span class="mi"&gt;151&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;We do. Onwards.&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-1" name="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""UPDATE ELECTORATES SET FEDERAL = TRUE WHERE ELECTORATE_PK &amp;gt; 415"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-2" name="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-3" name="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-3"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""SELECT COUNT(*) FROM ELECTORATES WHERE FEDERAL IS TRUE"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-4" name="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-4"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-5" name="rest_code_4d3cb694879e4cf29f2a93cc70a2ab01-5"&gt;&lt;/a&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;151&lt;/span&gt;&lt;span class="p"&gt;,)]&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Likewise, we'll set the others to &lt;cite&gt;federal=False&lt;/cite&gt;:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_c262ab0087cd4b74b61a28bede615c25-1" name="rest_code_c262ab0087cd4b74b61a28bede615c25-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""UPDATE ELECTORATES SET FEDERAL = FALSE WHERE ELECTORATE_PK &amp;lt; 416"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_c262ab0087cd4b74b61a28bede615c25-2" name="rest_code_c262ab0087cd4b74b61a28bede615c25-2"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Back to our queries. I want to see both sorts of electorates, but grouped by whether they are federal or
state electorates:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-1" name="rest_code_942574733e6f4f4c973987c88301bea4-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""SELECT E.STATENAME, E.ELECTORATE, E.FEDERAL FROM ELECTORATES E&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-2" name="rest_code_942574733e6f4f4c973987c88301bea4-2"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   WHERE E.ELECTORATE_PK IN&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-3" name="rest_code_942574733e6f4f4c973987c88301bea4-3"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                       (SELECT DISTINCT ELECTORATE_FK FROM GEOPOINTS WHERE LATITUDE BETWEEN -29.001 AND -28.995)&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-4" name="rest_code_942574733e6f4f4c973987c88301bea4-4"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   GROUP BY E.STATENAME, E.ELECTORATE, E.FEDERAL&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-5" name="rest_code_942574733e6f4f4c973987c88301bea4-5"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   ORDER BY STATENAME, ELECTORATE"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-6" name="rest_code_942574733e6f4f4c973987c88301bea4-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fedstate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-7" name="rest_code_942574733e6f4f4c973987c88301bea4-7"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;fedstate&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-8" name="rest_code_942574733e6f4f4c973987c88301bea4-8"&gt;&lt;/a&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Ballina'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Barwon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Clarence'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Lismore'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'New England'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Northern Tablelands'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Page'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'NSW'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Parkes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'QLD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Maranoa'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'QLD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Southern Downs'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'QLD'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Warrego'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Giles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Grey'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'SA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Stuart'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Durack'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Geraldton'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Kalgoorlie'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Moore'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'WA'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'North West Central'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-9" name="rest_code_942574733e6f4f4c973987c88301bea4-9"&gt;&lt;/a&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-10" name="rest_code_942574733e6f4f4c973987c88301bea4-10"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;tfy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-11" name="rest_code_942574733e6f4f4c973987c88301bea4-11"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-12" name="rest_code_942574733e6f4f4c973987c88301bea4-12"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"yes"&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-13" name="rest_code_942574733e6f4f4c973987c88301bea4-13"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-14" name="rest_code_942574733e6f4f4c973987c88301bea4-14"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-15" name="rest_code_942574733e6f4f4c973987c88301bea4-15"&gt;&lt;/a&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-16" name="rest_code_942574733e6f4f4c973987c88301bea4-16"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;fedstate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-17" name="rest_code_942574733e6f4f4c973987c88301bea4-17"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;fmtstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="si"&gt;{statename:6}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{electorate:30}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{federal}&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-18" name="rest_code_942574733e6f4f4c973987c88301bea4-18"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fmtstr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;federal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tfy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-19" name="rest_code_942574733e6f4f4c973987c88301bea4-19"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-20" name="rest_code_942574733e6f4f4c973987c88301bea4-20"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Ballina&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-21" name="rest_code_942574733e6f4f4c973987c88301bea4-21"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Barwon&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-22" name="rest_code_942574733e6f4f4c973987c88301bea4-22"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Clarence&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-23" name="rest_code_942574733e6f4f4c973987c88301bea4-23"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Lismore&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-24" name="rest_code_942574733e6f4f4c973987c88301bea4-24"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;New&lt;/span&gt; &lt;span class="n"&gt;England&lt;/span&gt;                    &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-25" name="rest_code_942574733e6f4f4c973987c88301bea4-25"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Northern&lt;/span&gt; &lt;span class="n"&gt;Tablelands&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-26" name="rest_code_942574733e6f4f4c973987c88301bea4-26"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Page&lt;/span&gt;                           &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-27" name="rest_code_942574733e6f4f4c973987c88301bea4-27"&gt;&lt;/a&gt;&lt;span class="n"&gt;NSW&lt;/span&gt;    &lt;span class="n"&gt;Parkes&lt;/span&gt;                         &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-28" name="rest_code_942574733e6f4f4c973987c88301bea4-28"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Maranoa&lt;/span&gt;                        &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-29" name="rest_code_942574733e6f4f4c973987c88301bea4-29"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Southern&lt;/span&gt; &lt;span class="n"&gt;Downs&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-30" name="rest_code_942574733e6f4f4c973987c88301bea4-30"&gt;&lt;/a&gt;&lt;span class="n"&gt;QLD&lt;/span&gt;    &lt;span class="n"&gt;Warrego&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-31" name="rest_code_942574733e6f4f4c973987c88301bea4-31"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Giles&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-32" name="rest_code_942574733e6f4f4c973987c88301bea4-32"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Grey&lt;/span&gt;                           &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-33" name="rest_code_942574733e6f4f4c973987c88301bea4-33"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Stuart&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-34" name="rest_code_942574733e6f4f4c973987c88301bea4-34"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Durack&lt;/span&gt;                         &lt;span class="n"&gt;yes&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-35" name="rest_code_942574733e6f4f4c973987c88301bea4-35"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Geraldton&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-36" name="rest_code_942574733e6f4f4c973987c88301bea4-36"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Kalgoorlie&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-37" name="rest_code_942574733e6f4f4c973987c88301bea4-37"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Moore&lt;/span&gt;
&lt;a id="rest_code_942574733e6f4f4c973987c88301bea4-38" name="rest_code_942574733e6f4f4c973987c88301bea4-38"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;North&lt;/span&gt; &lt;span class="n"&gt;West&lt;/span&gt; &lt;span class="n"&gt;Central&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;I could have added a &lt;cite&gt;WHERE E.FEDERAL = TRUE&lt;/cite&gt; to the query, too.&lt;/p&gt;
&lt;p&gt;Finally, let's see what state electorates in WA and SA are on the border:&lt;/p&gt;
&lt;pre class="code python"&gt;&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-1" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-1"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""SELECT STATENAME, ELECTORATE FROM ELECTORATES E&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-2" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-2"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   WHERE ELECTORATE_PK IN&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-3" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-3"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                       (SELECT DISTINCT ELECTORATE_FK FROM GEOPOINTS WHERE LATITUDE BETWEEN -60.00 AND -25.995&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-4" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-4"&gt;&lt;/a&gt;&lt;span class="s2"&gt;                           AND LONGITUDE BETWEEN 128.995 AND 129.1)&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-5" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-5"&gt;&lt;/a&gt;&lt;span class="s2"&gt;...                   AND FEDERAL = FALSE ORDER BY STATENAME, ELECTORATE"""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-6" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-6"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetchall&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-7" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-7"&gt;&lt;/a&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_res&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-8" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-8"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="si"&gt;{statename:6}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="si"&gt;{electorate}&lt;/span&gt;&lt;span class="s2"&gt;"""&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;statename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;electorate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;_res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-9" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-9"&gt;&lt;/a&gt;&lt;span class="o"&gt;...&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-10" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-10"&gt;&lt;/a&gt;&lt;span class="n"&gt;NT&lt;/span&gt;     &lt;span class="n"&gt;Namatjira&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-11" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-11"&gt;&lt;/a&gt;&lt;span class="n"&gt;SA&lt;/span&gt;     &lt;span class="n"&gt;Giles&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-12" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-12"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;Kalgoorlie&lt;/span&gt;
&lt;a id="rest_code_2beae5225a294a6fa13c6369b79d1f66-13" name="rest_code_2beae5225a294a6fa13c6369b79d1f66-13"&gt;&lt;/a&gt;&lt;span class="n"&gt;WA&lt;/span&gt;     &lt;span class="n"&gt;North&lt;/span&gt; &lt;span class="n"&gt;West&lt;/span&gt; &lt;span class="n"&gt;Central&lt;/span&gt;
&lt;/pre&gt;&lt;p&gt;Why do we have that electorate from the Northern Territory? It's because the coordinates are a bit fuzzy and we had to use a range (the BETWEEN) in our query.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="finally"&gt;
&lt;h2&gt;Finally&lt;/h2&gt;
&lt;p&gt;I apologise, because while this was supposed to be a &lt;em&gt;brief&lt;/em&gt; introduction I did get side-tracked with data investigation.
I suppose that's an occupational hazard since I'm a Data Engineer working for a company which provides GIS-related services.
Anyway, in terms of depth, this was definitely only scratching the surface of what is possible with Python and databases. I
encourage you to go and read the &lt;a class="reference external" href="https://www.python.org/dev/peps/pep-0249/"&gt;Python Database API&lt;/a&gt; as well as the SQL reference manual(s) for your chosen database and
its binding documentation.&lt;/p&gt;
&lt;!-- put references after this point --&gt;
&lt;/section&gt;</description><category>cx_Oracle</category><category>Data Engineering</category><category>Data Investigation</category><category>Database</category><category>Databases</category><category>Oracle</category><category>PEP 249</category><category>PostgreSQL</category><category>programming</category><category>psycopg2</category><category>Python</category><category>software engineering</category><category>SQL</category><guid>https://www.jmcpdotcom.com/blog/posts/2020-06-03-a-brief-introduction-to-the-python-database-api/</guid><pubDate>Tue, 02 Jun 2020 23:37:00 GMT</pubDate></item></channel></rss>