This section introduces
This section provides a simplified demonstration of a
erl -mnesia dir '"/tmp/funky"' Erlang (BEAM) emulator version 4.9 Eshell V4.9 (abort with ^G) 1> 1> mnesia:create_schema([node()]). ok 2> mnesia:start(). ok 3> mnesia:create_table(funky, []). {atomic,ok} 4> mnesia:info(). ---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Pending (remote) transactions <--- ---> Active (local) transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- funky : with 0 records occupying 269 words of mem schema : with 2 records occupying 353 words of mem ===> System info in version "1.0", debug level = none <=== opt_disc. Directory "/tmp/funky" is used. use fall-back at restart = false running db nodes = [nonode@nohost] stopped db nodes = [] remote = [] ram_copies = [funky] disc_copies = [schema] disc_only_copies = [] [{nonode@nohost,disc_copies}] = [schema] [{nonode@nohost,ram_copies}] = [funky] 1 transactions committed, 0 aborted, 0 restarted, 1 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: [] ok ]]>
In this example, the following actions are performed:
A
This example shows how to create a database called
The database model is as follows:
There are three relationships between these entities:
First the record definitions are entered into a text file
named
The structure defines six tables in the database. In
The current version of
For example, the table for employees is created with the
function
The following shell interaction starts
% erl -mnesia dir '"/ldisc/scratch/Mnesia.Company"' Erlang (BEAM) emulator version 4.9 Eshell V4.9 (abort with ^G) 1> mnesia:create_schema([node()]). ok 2> mnesia:start(). ok
The following program module creates and populates previously defined tables:
The following commands and functions are used to initiate the
Continuing the dialogue with the Erlang shell produces the following:
company:init(). {atomic,ok} 4> mnesia:info(). ---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Pending (remote) transactions <--- ---> Active (local) transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- in_proj : with 0 records occuping 269 words of mem at_dep : with 0 records occuping 269 words of mem manager : with 0 records occuping 269 words of mem project : with 0 records occuping 269 words of mem dept : with 0 records occuping 269 words of mem employee : with 0 records occuping 269 words of mem schema : with 7 records occuping 571 words of mem ===> System info in version "1.0", debug level = none <=== opt_disc. Directory "/ldisc/scratch/Mnesia.Company" is used. use fall-back at restart = false running db nodes = [nonode@nohost] stopped db nodes = [] remote = [] ram_copies = [at_dep,dept,employee,in_proj,manager,project] disc_copies = [schema] disc_only_copies = [] [{nonode@nohost,disc_copies}] = [schema] [{nonode@nohost,ram_copies}] = [employee,dept,project,manager,at_dep,in_proj] 6 transactions committed, 0 aborted, 0 restarted, 6 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: [] ok ]]>
A set of tables is created. The function
The function
To write a function that inserts an employee record into the
database, there must be an
The
The function
The function can be used as follows:
Emp = #employee{emp_no= 104732,
name = klacke,
salary = 7,
sex = male,
phone = 98108,
room_no = {221, 015}},
insert_emp(Emp, 'B/SFR', [Erlang, mnesia, otp]).
For information about Funs, see "Fun Expressions" in
section
After the insertion of the employee named
This
This
This
There is no difference between rows in a table and
A
The record
After adding more records to the
{employee, 104465, "Johnson Torbjorn", 1, male, 99184, {242,038}}.
{employee, 107912, "Carlsson Tuula", 2, female,94556, {242,056}}.
{employee, 114872, "Dacker Bjarne", 3, male, 99415, {221,035}}.
{employee, 104531, "Nilsson Hans", 3, male, 99495, {222,026}}.
{employee, 104659, "Tornkvist Torbjorn", 2, male, 99514, {222,022}}.
{employee, 104732, "Wikstrom Claes", 2, male, 99586, {221,015}}.
{employee, 117716, "Fedoriw Anna", 1, female,99143, {221,031}}.
{employee, 115018, "Mattsson Hakan", 3, male, 99251, {203,348}}.
{dept, 'B/SF', "Open Telecom Platform"}.
{dept, 'B/SFP', "OTP - Product Development"}.
{dept, 'B/SFR', "Computer Science Laboratory"}.
%% projects
{project, erlang, 1}.
{project, otp, 2}.
{project, beam, 3}.
{project, mnesia, 5}.
{project, wolf, 6}.
{project, documentation, 7}.
{project, www, 8}.
These three tables,
{manager, 104465, 'B/SF'}.
{manager, 104465, 'B/SFP'}.
{manager, 114872, 'B/SFR'}.
{at_dep, 104465, 'B/SF'}.
{at_dep, 107912, 'B/SF'}.
{at_dep, 114872, 'B/SFR'}.
{at_dep, 104531, 'B/SFR'}.
{at_dep, 104659, 'B/SFR'}.
{at_dep, 104732, 'B/SFR'}.
{at_dep, 117716, 'B/SFP'}.
{at_dep, 115018, 'B/SFP'}.
{in_proj, 104465, otp}.
{in_proj, 107912, otp}.
{in_proj, 114872, otp}.
{in_proj, 104531, otp}.
{in_proj, 104531, mnesia}.
{in_proj, 104545, wolf}.
{in_proj, 104659, otp}.
{in_proj, 104659, wolf}.
{in_proj, 104732, otp}.
{in_proj, 104732, mnesia}.
{in_proj, 104732, erlang}.
{in_proj, 117716, otp}.
{in_proj, 117716, documentation}.
{in_proj, 115018, otp}.
{in_proj, 115018, mnesia}.
The room number is an attribute of the employee
record. This is a structured attribute that consists of a
tuple. The first element of the tuple identifies a corridor,
and the second element identifies the room in that
corridor. An alternative is to represent this as a record
The
Retrieving data from DBMS is usually to be done with the
functions
Since it is desired to update the record using the function
To read the values from the table directly is not always possible.
It can be needed to search one or more tables to get the
wanted data, and this is done by writing database queries. Queries
are always more expensive operations than direct lookups done with
Two methods are available for writing database queries:
The following function extracts the names of the female employees stored in the database:
mnesia:select(employee, [{#employee{sex = female, name = '$1', _ = '_'},[], ['$1']}]).
The
This function can be called from the shell as follows:
(klacke@gin)1> company:all_females(). {atomic, ["Carlsson Tuula", "Fedoriw Anna"]}
For a description of
This section contains simple introductory examples only. For
a full description of the QLC query language, see the
Using QLC can be more expensive than using
The following function extracts a list of female employees from the database:
Q = qlc:q([E#employee.name || E mnesia:table(employee), E#employee.sex == female]), qlc:e(Q),
Accessing
This function can be called from the shell as follows:
(klacke@gin)1> company:females(). {atomic, ["Carlsson Tuula", "Fedoriw Anna"]}
In traditional relational database terminology, this operation is called a selection, followed by a projection.
The previous list comprehension expression contains a number of syntactical elements:
Hence, the previous list comprehension demonstrates the
formation of the list
The whole list comprehension must be given to the function
List comprehensions with low-level
The function
Example:
33>company:raise_females(33). {atomic,2}