common-lisp
Trabajando con bases de datos
Buscar..
Uso simple de PostgreSQL con Postmodern
Postmodern es una biblioteca para interactuar con la base de datos relacional PostgreSQL . Ofrece varios niveles de acceso a PostgreSQL, desde la ejecución de consultas SQL representadas como cadenas, o como listas, hasta un mapeo objeto-relacional.
La base de datos utilizada en los siguientes ejemplos se puede crear con estas sentencias de SQL:
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}');
El primer ejemplo muestra el resultado de una consulta simple que devuelve una relación:
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
Tenga en cuenta que el resultado se puede devolver como una lista de listas o listas que agregan los parámetros opcionales :alists
o :plists
a la función de consulta.
Una alternativa a la query
es doquery
, para iterar sobre los resultados de una consulta. Sus parámetros son query (&rest names) &body body
, donde los nombres están vinculados a los valores en la fila en cada iteración:
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
Cuando la consulta requiere parámetros, se pueden usar instrucciones preparadas:
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
La función prepare
recibe una consulta con marcadores $1
posición $1
, $2
, etc. y devuelve una nueva función que requiere un parámetro para cada marcador de posición y ejecuta la consulta cuando se le llama con el número correcto de argumentos.
En caso de actualizaciones, la función exec
devuelve el número de tuplas modificadas (las dos declaraciones DDL se incluyen en una transacción):
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
Además de escribir consultas SQL como cadenas, se pueden usar listas de palabras clave, símbolos y constantes, con una sintaxis que recuerda a 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