common-lisp
Werken met databases
Zoeken…
Eenvoudig gebruik van PostgreSQL met Postmodern
Postmodern is een bibliotheek om te communiceren met de relationele database PostgreSQL . Het biedt verschillende toegangsniveaus voor PostgreSQL, van het uitvoeren van SQL-query's die worden weergegeven als tekenreeksen of als lijsten, tot een object-relationele toewijzing.
De database die in de volgende voorbeelden wordt gebruikt, kan met deze SQL-instructies worden gemaakt:
create table employees
(empid integer not null primary key,
name text not null,
birthdate date not null,
skills text[] not null);
insert into employees (empid, name, birthdate, skills) values
(1, 'John Orange', '1991-07-26', '{C, Java}'),
(2, 'Mary Red', '1989-04-14', '{C, Common Lisp, Hunchentoot}'),
(3, 'Ron Blue', '1974-01-17', '{JavaScript, Common Lisp}'),
(4, 'Lucy Green', '1968-02-02', '{Java, JavaScript}');
Het eerste voorbeeld toont het resultaat van een eenvoudige query die een relatie retourneert:
CL-USER> (ql:quickload "postmodern") ; load the system postmodern (nickname: pomo)
("postmodern")
CL-USER> (let ((parameters '("database" "dbuser" "dbpass" "localhost")))
(pomo:with-connection parameters
(pomo:query "select name, skills from employees")))
(("John Orange" #("C" "Java")) ; output manually edited!
("Mary Red" #("C" "Common Lisp" "Hunchentoot"))
("Ron Blue" #("JavaScript" "Common Lisp"))
("Lucy Green" #("Java" "JavaScript")))
4 ; the second value is the size of the result
Merk op dat het resultaat kan worden geretourneerd als een lijst met alists of plists die de optionele parameters :alists
of :plists
aan de :plists
.
Een alternatief voor query
is doquery
, om de resultaten van een query te herhalen. De parameters zijn query (&rest names) &body body
, waarbij namen bij elke iteratie gebonden zijn aan de waarden in de rij:
CL-USER> (let ((parameters '("database" "dbuser" "dbpass" "localhost")))
(pomo:with-connection parameters
(format t "The employees that knows Java are:~%")
(pomo:doquery "select empid, name from employees where skills @> '{Java}'" (i n)
(format t "~a (id = ~a)~%" n i))))
The employees that knows Java are:
John Orange (id = 1)
Lucy Green (id = 4)
NIL
2
Wanneer de query parameters vereist, kan men voorbereide instructies gebruiken:
CL-USER> (let ((parameters '("database" "dbuser" "dbpass" "localhost")))
(pomo:with-connection parameters
(funcall
(pomo:prepare "select name, skills from employees where skills @> $1")
#("Common Lisp")))) ; find employees with skills including Common Lisp
(("Mary Red" #("C" "Common Lisp" "Hunchentoot"))
("Ron Blue" #("JavaScript" "Common Lisp")))
2
De functie prepare
ontvangt een query met tijdelijke aanduidingen $1
, $2
, enz. En retourneert een nieuwe functie die één parameter vereist voor elke tijdelijke aanduiding en voert de query uit wanneer deze met het juiste aantal argumenten wordt aangeroepen.
In het geval van updates retourneert de functie exec
het aantal gewijzigde tupels (de twee DDL-instructies zijn ingesloten in een transactie):
CL-USER> (let ((parameters '("database" "dbuser" "dbpass" "localhost")))
(pomo:with-connection parameters
(pomo:ensure-transaction
(values
(pomo:execute "alter table employees add column salary integer")
(pomo:execute "update employees set salary =
case when skills @> '{Common Lisp}'
then 100000 else 50000 end")))))
0
4
Naast het schrijven van SQL-query's als tekenreeksen, kan men ook gebruik maken van lijsten met trefwoorden, symbolen en constanten, met een syntaxis die doet denken aan lisp (S-SQL):
CL-USER> (let ((parameters '("database" "dbuser" "dbpass" "localhost")))
(pomo:with-connection parameters
(pomo:query (:select 'name :from 'employees :where (:> 'salary 60000)))))
(("Mary Red") ("Ron Blue"))
2