By Gabriel Alfred Krupa
Video overview: YouTube video
The purpose of this database is to keep track of artists' creation, their value, owners, and satisfactory status thereof. Whilst meticulously noting who and how gained the ownership of any piece of artwork.
Entities in the scope of this database are, as follows:
Artists, containing first and last name, date of birth, and main focus in artsArt, containing the name of the piece, category, and year of its creationCategories, including almost every form of art known and their subdomains and genresOwners, basic information about the ownershipRatings, include who, when and how rated certain pieces of artTransactions, contains information about every exchange of the artwork
Out of scope are elements such as an average price of artwork by an artist, owner's financial balance, top 10 artworks by genre, subdomain and domain, top 10 most-sought-after artists, and more.
This database supports:
- CRUD operations for all tables
- Tracking any exchange of artist's work
- Adding multiple rating on each artwork, by which the artist's rating can be determined
For now, database does not support features of financial nature, such as adding, removing or transferring funds.
Entities are made in SQLite table and have the following schema.
The artists table includes:
id, sets unique ID for each artist and has type affinity ofINTEGER. This column, as is the convention, has thePRIMARY KEYconstraint applied.first_name, specifies the artist's first name and has type affinity ofTEXT. Type affinity ofTEXTis commonly used for columns where name is specified.NOT NULLconstraint applied because the artist must have a first name.last_name, specifies the artist's last name and has type affinity ofTEXT. Reason for usingTEXTis specified underfirst_name.NOT NULLconstraint applied because the artist must have a last name.dob, specifies the artist's date of birth inYYYY-MM-DDformat, supportsYYYY-MM-DD HH-MMformat. This column has type affinity ofNUMERIC, such is used for dates and more.NOT NULLconstraint applied because the artist was born some point in time.join_date, sets timestamp of the exact moment when the artist's row is inserted into the table.NUMERICtype affinity for the same reason as for thedobcolumn. Timestamp is automatically generated byDEFAULT CURRENT_TIMESTAMP.NOT NULLconstraint applied to ensure that the column is not empty.category_id, specifies the artist's main domain, subdomain and genre of focus.FOREIGN KEYreferences the defaultrowidcolumn inCategoriestable to ensure the data integrity.
The art table includes the following:
id, sets unique ID for artwork. Type affinity ofINTEGERset andPRIMARY KEYconstraint applied.name, specifies the name of the artwork and has type affinity ofTEXT.NOT NULLset to ensure that the artwork's name is inserted and it has to have a name.year, specifies what year the artwork was created inYYYYformat and is of type affinityINTEGER.NOT NULLspecified to make avoid empty column.artist_id, specifies the author of the artwork.FOREIGN KEYconstraint applied, referencing theidcolumn fromartisttable to ensure data integrity.ON DELETE CASCADEensure that the row is deleted when the author is removed from theartisttable.category_id, specifies the category of the artwork.FOREIGN KEYconstraint applied, referencing therowidcolumn fromcategoriestable to ensure data integrity.ON DELETE CASCADEensure that the row is deleted when the category is removed from thecategoriestable.
The categories table includes:
rowidcolumn is generated by default for each row.domain, specifies the general form of art.subdoman, specifies the type of art under its general art form.genre, specifies the genre of the type.
All columns, except rowid, have type affinity of TEXT and NOT NULL constraint.
UNIQUE constraint was not applied because there many subdomains, and genres with the same name
under different domains.
The owners table contains the following:
id, sets unique ID for each owner as anINTEGER.PRIMARY KEYconstraint applied.first_name, specifies the owner's first name and has type affinity ofTEXT. Type affinity ofTEXTis commonly used for columns where name is specified.NOT NULLconstraint applied because the owner must have a first name.last_name, specifies owner's last name and has type affinity ofTEXT. Reason for usingTEXTis specified underfirst_name.NOT NULLconstraint applied because owner must have a last name.username, specifies owner's username and has type affinity ofTEXT. Reason for usingTEXTis specified underfirst_name.NOT NULLconstraint applied because owner must have a username.UNIQUEconstraint applied because no duplicate usernames are allowed.
At the current state of database, this table introduces redundancies, and increased disk usage.
However, if we upgrade the schema of database and introduce more complexities, such as adding new columns to this table, financial features, keeping track of how long did an owner hold a certain artwork, etc, we would mitigate redundancies, unnecessary disk usage, and could have VIEW to avoid unnecessary display of PII (Personal Identifiable Information).
The ratings table includes:
id, sets unique ID for each rating as anINTEGER.PRIMARY KEYconstraint applied.owner_id, specifies the owner of the artwork as anINTEGER.FOREIGN KEYconstraint applied, referencing theidcolumn fromownerstable to ensure data integrity.art_id, specifies the artwork as anINTEGER.FOREIGN KEYconstraint applied, referencing theidcolumn fromarttable to ensure data integrity.timestamp, sets timestamp of the exact moment rating was given. Type affinity ofNUMERICset, as is appropriate from timestamps. Timestamp is automatically generated byDEFAULT CURRENT_TIMESTAMP.NOT NULLconstraint applied to ensure that the column is not empty.rating, represents given rating of the artwork.NOT NULLconstraint applied to ensure that the column is not empty.DEFAULT 1constraint sets the rating to 1, if no rating was provided.CHECK("rating" BETWEEN 1 AND 10)ensures that data is valid by checking if the given rating is in range 1 through 10.
A description column could be added to the ratings table, in which the owner can provide a lengthy description of the artwork in question.
The transactions table contains:
id, sets unique ID for each transaction as anINTEGER.PRIMARY KEYconstraint applied.owner_id, specifies the new owner of the artwork as anINTEGER.FOREIGN KEYconstraint applied, referencing theidcolumn fromownerstable to ensure data integrity.art_id, specifies the artwork as anINTEGER.FOREIGN KEYconstraint applied, referencing theidcolumn fromarttable to ensure data integrity.price, specifies the determined price of artwork in US cents as anINTEGER, in order to prevent any miscalculation which typically occur with storage class representing values in decimal format.NOT NULLconstraint applied to ensure that column is not empty.action, specifies an action by which the new owner came into possession of the artwork. Type affinityTEXTset because it is convenient for possible actions.NOT NULLconstraint applied to ensure that column is not empty.CHECK("action" IN ('bought', 'sold', 'gifted', 'created'))determines if the action specified is allowed.
Artist can make one or more pieces of Art. Art can only have one creator, Artist. Artist and Art can each only be in one Category. Category can have zero or more both Artist and Art. Art can have one and only one active Owner. Owner can have one or more Art. Owner must have at least one Rating, vice versa. Art can have one or more Rating. Rating can have zero or more Art. Transaction must have at least one Art, vice versa.
Seeing as users will most likely want to query the database for either artist, owner, and category information.
There are indexes for artists, owners, categories, and transactions.
artist_idx decreases the search speed on id, last_name, and category columns.
owner_idx covers id and username columns.
category_idx includes rowid and domain columns.
transaction_idx contains id, owner_id, and art_id columns.
Artists have rating based on merit, ie. that is the view called artist_rating.
Schema for that view is shown below:
CREATE VIEW "artist_rating" AS
SELECT
"artists"."id" AS "Artist ID",
"artists"."first_name" AS "First Name",
"artists"."last_name" AS "Last Name",
ROUND(SUM("ratings"."rating")/COUNT("ratings"."rating"), 2) AS "Rating"
FROM "artists"
JOIN "art" ON "artists"."id" = "art"."artist_id"
JOIN "ratings" ON "art"."id" = "ratings"."art_id"
GROUP BY "Artist ID"
ORDER BY "Last Name";
Trigger to automate entry into owners, transactions, and ratings table when new art is created.
Schema:
CREATE TRIGGER new_art_created AFTER INSERT ON art
BEGIN
-- Set the artist as the owner if it was 'created'
INSERT OR IGNORE INTO owners(first_name, last_name, username)
SELECT
first_name,
last_name,
first_name || last_name || id
FROM artists
WHERE id = NEW.artist_id;
INSERT INTO transactions (owner_id, art_id, price, action)
SELECT id, NEW.id, 0, 'created' FROM owners WHERE username = first_name || last_name || NEW.artist_id
ORDER BY id LIMIT 1;
INSERT INTO ratings (owner_id, art_id, rating)
SELECT id, NEW.id, 1 FROM owners WHERE username = first_name || last_name || NEW.artist_id
ORDER BY id LIMIT 1;
END;
Current state of database is not scalable, nor safe. It lacks security, access control, mitigation of its glaring vulnerabilities, can be optimized to improve performance.
It does not represent the relationship between owners and artists well.
Art can only have one artist, meaning collaboration is not supported.
Art can only be one category, needs many-to-many relationships with categories table.
