Python is awesome. I like Python very much, but there are some cases where Python’s performance is just not enough. What other options do we have?
Well, there’s for example GoLang
Problem with GoLang is that there is not a lot on the Internet about using it with Oracle Databases. Let me show you some basic steps for configuring the environment.
The first step is to install GoLang – instructions can be found in here: https://golang.org/doc/install
To connect to Oracle, you need Oracle Client (it can be Oracle Instant Client).
I will configure my environment on my MAC and use Oracle Instant Client for MAC
1 | piclerick:~ inter$ mkdir oracle |
2 | piclerick:~ inter$ cd oracle |
3 | piclerick:oracle inter$ ls |
4 | piclerick:oracle inter$ unzip ~/Downloads/instantclient-basic-macos.x64-18.1.0.0.0.zip |
5 | Archive: /Users/inter/Downloads/instantclient-basic-macos.x64-18.1.0.0.0.zip |
6 | inflating: instantclient_18_1/BASIC_README |
7 | inflating: instantclient_18_1/adrci |
8 | inflating: instantclient_18_1/genezi |
9 | linking: instantclient_18_1/libclntsh.dylib -> libclntsh.dylib.18.1 |
10 | inflating: instantclient_18_1/libclntsh.dylib.18.1 |
11 | inflating: instantclient_18_1/libclntshcore.dylib.18.1 |
12 | inflating: instantclient_18_1/libnnz18.dylib |
13 | linking: instantclient_18_1/libocci.dylib -> libocci.dylib.18.1 |
14 | inflating: instantclient_18_1/libocci.dylib.18.1 |
15 | inflating: instantclient_18_1/libociei.dylib |
16 | inflating: instantclient_18_1/libocijdbc18.dylib |
17 | inflating: instantclient_18_1/libons.dylib |
18 | inflating: instantclient_18_1/liboramysql18.dylib |
19 | creating: instantclient_18_1/network/ |
20 | inflating: instantclient_18_1/ojdbc8.jar |
21 | inflating: instantclient_18_1/ucp.jar |
22 | inflating: instantclient_18_1/uidrvci |
23 | inflating: instantclient_18_1/xstreams.jar |
24 | creating: instantclient_18_1/network/admin/ |
25 | inflating: instantclient_18_1/network/admin/README |
26 | finishing deferred symbolic links: |
27 | instantclient_18_1/libclntsh.dylib -> libclntsh.dylib.18.1 |
28 | instantclient_18_1/libocci.dylib -> libocci.dylib.18.1 |
29 | piclerick:oracle inter$ unzip ~/Downloads/instantclient-sqlplus-macos.x64-18.1.0.0.0.zip |
30 | Archive: /Users/inter/Downloads/instantclient-sqlplus-macos.x64-18.1.0.0.0.zip |
31 | inflating: instantclient_18_1/SQLPLUS_README |
32 | inflating: instantclient_18_1/glogin.sql |
33 | inflating: instantclient_18_1/libsqlplus.dylib |
34 | inflating: instantclient_18_1/libsqlplusic.dylib |
35 | inflating: instantclient_18_1/sqlplus |
36 | piclerick:oracle inter$ unzip ~/Downloads/instantclient-tools-macos.x64-18.1.0.0.0.zip |
37 | Archive: /Users/inter/Downloads/instantclient-tools-macos.x64-18.1.0.0.0.zip |
38 | inflating: instantclient_18_1/TOOLS_README |
39 | inflating: instantclient_18_1/exp |
40 | inflating: instantclient_18_1/expdp |
41 | inflating: instantclient_18_1/imp |
42 | inflating: instantclient_18_1/impdp |
43 | inflating: instantclient_18_1/libnfsodm18.dylib |
44 | inflating: instantclient_18_1/sqlldr |
45 | inflating: instantclient_18_1/wrc |
46 | piclerick:oracle inter$ unzip ~/Downloads/instantclient-sdk-macos.x64-18.1.0.0.0-2.zip |
47 | Archive: /Users/inter/Downloads/instantclient-sdk-macos.x64-18.1.0.0.0-2.zip |
48 | creating: instantclient_18_1/sdk/ |
49 | creating: instantclient_18_1/sdk/admin/ |
50 | inflating: instantclient_18_1/sdk/admin/oraaccess.xsd |
51 | creating: instantclient_18_1/sdk/demo/ |
52 | inflating: instantclient_18_1/sdk/demo/cdemo81.c |
53 | inflating: instantclient_18_1/sdk/demo/demo.mk |
54 | inflating: instantclient_18_1/sdk/demo/occidemo.sql |
55 | inflating: instantclient_18_1/sdk/demo/occidemod.sql |
56 | inflating: instantclient_18_1/sdk/demo/occidml.cpp |
57 | inflating: instantclient_18_1/sdk/demo/occiobj.cpp |
58 | inflating: instantclient_18_1/sdk/demo/occiobj.typ |
59 | inflating: instantclient_18_1/sdk/demo/oraaccess.xml |
60 | inflating: instantclient_18_1/sdk/demo/setuporamysql.sh |
61 | creating: instantclient_18_1/sdk/include/ |
62 | inflating: instantclient_18_1/sdk/include/ldap.h |
63 | inflating: instantclient_18_1/sdk/include/nzerror.h |
64 | inflating: instantclient_18_1/sdk/include/nzt.h |
65 | inflating: instantclient_18_1/sdk/include/occi.h |
66 | inflating: instantclient_18_1/sdk/include/occiAQ.h |
67 | inflating: instantclient_18_1/sdk/include/occiCommon.h |
68 | inflating: instantclient_18_1/sdk/include/occiControl.h |
69 | inflating: instantclient_18_1/sdk/include/occiData.h |
70 | inflating: instantclient_18_1/sdk/include/occiObjects.h |
71 | inflating: instantclient_18_1/sdk/include/oci.h |
72 | inflating: instantclient_18_1/sdk/include/oci1.h |
73 | inflating: instantclient_18_1/sdk/include/oci8dp.h |
74 | inflating: instantclient_18_1/sdk/include/ociap.h |
75 | inflating: instantclient_18_1/sdk/include/ociapr.h |
76 | inflating: instantclient_18_1/sdk/include/ocidef.h |
77 | inflating: instantclient_18_1/sdk/include/ocidem.h |
78 | inflating: instantclient_18_1/sdk/include/ocidfn.h |
79 | inflating: instantclient_18_1/sdk/include/ociextp.h |
80 | inflating: instantclient_18_1/sdk/include/ocikpr.h |
81 | inflating: instantclient_18_1/sdk/include/ociver.h |
82 | inflating: instantclient_18_1/sdk/include/ocixmldb.h |
83 | inflating: instantclient_18_1/sdk/include/ocixstream.h |
84 | inflating: instantclient_18_1/sdk/include/odci.h |
85 | inflating: instantclient_18_1/sdk/include/orastruc.h |
86 | inflating: instantclient_18_1/sdk/include/oratypes.h |
87 | inflating: instantclient_18_1/sdk/include/oraxml.h |
88 | inflating: instantclient_18_1/sdk/include/oraxml.hpp |
89 | inflating: instantclient_18_1/sdk/include/oraxmlcg.h |
90 | inflating: instantclient_18_1/sdk/include/oraxsd.h |
91 | inflating: instantclient_18_1/sdk/include/oraxsd.hpp |
92 | inflating: instantclient_18_1/sdk/include/ori.h |
93 | inflating: instantclient_18_1/sdk/include/orid.h |
94 | inflating: instantclient_18_1/sdk/include/orl.h |
95 | inflating: instantclient_18_1/sdk/include/oro.h |
96 | inflating: instantclient_18_1/sdk/include/ort.h |
97 | inflating: instantclient_18_1/sdk/include/xa.h |
98 | inflating: instantclient_18_1/sdk/include/xml.h |
99 | inflating: instantclient_18_1/sdk/include/xml.hpp |
100 | inflating: instantclient_18_1/sdk/include/xmlctx.hpp |
101 | inflating: instantclient_18_1/sdk/include/xmldav.h |
102 | inflating: instantclient_18_1/sdk/include/xmldf.h |
103 | inflating: instantclient_18_1/sdk/include/xmlerr.h |
104 | inflating: instantclient_18_1/sdk/include/xmlev.h |
105 | inflating: instantclient_18_1/sdk/include/xmlotn.h |
106 | inflating: instantclient_18_1/sdk/include/xmlotn.hpp |
107 | inflating: instantclient_18_1/sdk/include/xmlproc.h |
108 | inflating: instantclient_18_1/sdk/include/xmlsch.h |
109 | inflating: instantclient_18_1/sdk/include/xmlsoap.h |
110 | inflating: instantclient_18_1/sdk/include/xmlsoap.hpp |
111 | inflating: instantclient_18_1/sdk/include/xmlsoapc.hpp |
112 | inflating: instantclient_18_1/sdk/include/xmlurl.h |
113 | inflating: instantclient_18_1/sdk/include/xmlxptr.h |
114 | inflating: instantclient_18_1/sdk/include/xmlxsl.h |
115 | inflating: instantclient_18_1/sdk/include/xmlxvm.h |
116 | inflating: instantclient_18_1/sdk/ott |
117 | extracting: instantclient_18_1/sdk/ottclasses.zip |
118 | inflating: instantclient_18_1/sdk/SDK_README |
To connect to Oracle, we will use goracle – it is a package which is a database/sql/driver.Driver for connecting to Oracle DB, using Anthony Tuininga’s excellent OCI wrapper, ODPI-C.
Let’s get the package:
1 | piclerick:~ inter$ go get gopkg. in /goracle.v2 |
Now we can set the environment variables and create our source code:
1 | piclerick:~ inter$ export ORACLE_HOME=/Users/inter/oracle/instantclient_18_1 |
2 | piclerick:~ inter$ export DYLD_LIBRARY_PATH=/Users/inter/oracle/instantclient_18_1 |
3 | piclerick:~ inter$ vim chatt_with_oracle.go |
The base for our script will look like this:
7 | _ "gopkg.in/goracle.v2" |
Please note that we have to import goracle a bit differently than other packages – with "_" prefix. That’s because we will connect to the database like this: sql.Open("goracle", conn). So the "goracle" won’t be used directly in a code but as a string literal to SQL driver.
Let’s create a connection to the database and execute a simple query
7 | _ "gopkg.in/goracle.v2" |
12 | db, err := sql.Open( "goracle" , "hr/hr@192.168.56.18:1521/rokoko" ) |
23 | rows, err := db.Query( "select count(1) from employees" ) |
Now we can compile our program and execute it:
1 | piclerick:~ inter$ go build chatt_with_oracle.go |
2 | piclerick:~ inter$ ./chatt_with_oracle |
Great! Let’s add more rows to the output and additional bind variable:
7 | _ "gopkg.in/goracle.v2" |
12 | db, err := sql.Open( "goracle" , "hr/hr@192.168.56.18:1521/rokoko" ) |
24 | rows, err := db.Query( "select first_name, last_name, salary from employees where department_id=:1" , deptId) |
33 | var fname, lname string |
37 | rows.Scan(&fname, &lname, &salary) |
38 | fmt.Println(fname, lname, salary) |
And here’s the result:
1 | piclerick:~ inter$ ./chatt_with_oracle |
If you want to execute PL/SQL function or procedure and get the results, you can use sql.Out interface. For example, let’s create a sample PL/SQL function:
2 | Zapisano file afiedt.buf |
4 | 1 create or replace function f_get_dept_avg_sal(p_dept_id number) return number is |
7 | 4 select avg (salary) into v_avg_sal |
9 | 6 where e.department_id=p_dept_id; |
Now we can add a simple PL/SQL block to our GO function and use Exec method and sql.Out interface:
7 | _ "gopkg.in/goracle.v2" |
12 | db, err := sql.Open( "goracle" , "hr/hr@192.168.56.18:1521/rokoko" ) |
24 | rows, err := db.Query( "select first_name, last_name, salary from employees where department_id=:1" , deptId) |
33 | var fname, lname string |
37 | rows.Scan(&fname, &lname, &salary) |
38 | fmt.Println(fname, lname, salary) |
45 | db.Exec( "begin :1 := f_get_dept_avg_sal(:2); end;" , sql.Out{Dest: &avgSal}, deptId) |
47 | fmt.Printf( "AVG salary in department %d is %f\n" , deptId, avgSal) |
And here’s the result:
1 | piclerick:~ inter$ go build chatt_with_oracle.go |
2 | piclerick:~ inter$ ./chatt_with_oracle |
5 | AVG salary in department 20 is 19000.000000 |
And it’s simple as that 🙂