Вы находитесь на странице: 1из 45

The Snooty Cat Festival Company

Case Study

Database Principles

Overview

The Snooty Cat Festival Company organises many festivals around the UK. As of 2017 they
have been in business for seven years and have built a large client base in this time. They
organise many types of festivals, which may be music festivals, folk festivals, steam engine
festivals, car festivals or food festivals to name but a few. They use their organisational skills
and contacts to address the needs of their clients.

There is a large Music Festival at Stonehenge next year (Summer 2018) which they have
won the bid to organise and manage.

The company have agreed to organise the following:

The site and site arrangements including camping, fencing and security
Provide the stage, lights, sound equipment for the bands
Site amenities such as toilets and showers
The bands that will play at the festival
On site vendors providing food, drinks, trinkets, camping equipment, wellies, t-shirts,
souvenirs etc. etc.
Marketing the event, both traditionally and through social media
Ticket sales.

Many of the functions are outsourced to other companies such as security firms, fencing
contractors, vendors and agents of the bands that are playing. However it is the Snooty Cat
Company that have to ensure that all these people have been contacted, dates are agreed,
arrangements are made and requirements are clear.

The clients pay Snooty Cat to organise the festival and this payment has to cover all the
costs incurred in setting up the event. It is the client who gets the money from the ticket
sales, not Snooty Cat – they just facilitate the sales. The only other money Snooty Cat
makes is from charging the vendors (food and supplies) a site pitch at the festival.

The Database System

Previously, events have been managed using Excel Spreadsheets, letters, emails, diaries,
post it notes and a very large Gantt chart on the office wall. As they are growing they are
starting to find that they are managing multiple festivals at the same time. The main
spreadsheet is now 10,000 rows and has started to get very slow and it is becoming difficult
to find information easily. They now would like one integrated information system to help
them manage their work and provide instant information available to everyone in the
company. They have had problems in the past when a member of staff has gone off sick and
nobody else knows where the information is or how much of the job is still left to do.

The main driver for Snooty Cat Festivals is to have is an information system in place to
manage the Stonehenge event in 2018.

The Snooty Cat Page | 1


The Snooty Cat Festival Company
Outline Requirements

o Record information about all the suppliers, outsourced companies, agents


etc. including what they are providing, what they have agreed to do and the
date they were contacted.
o Record the costs for each of the services
o Record information as to which bands are playing, what time they are on
stage, how long their set is and any special requirements the bands have
requested.
o Record which vendors will be on site, arrival date / time and departure
Date / time and ensure that there are a range of services and not too many of
any one particular service (e.g. ensuring there are different types of food
available)
o Record that there are arrangements for First Aid, they use St John Ambulance
o Record which Snooty Cat staff are managing the various functions or have
specific tasks – one may be assigned to look after the bands needs another
to check all the security is in place and the security firm are happy.

Additionally the system needs to:

o Manage tickets sales to festival goers


o Record payments made to all parties, Snooty Cat Festivals will have to pay
the land owner for rent of the fields, the bands to play, security firms, fencing
firms, companies that provide stage, sounds and lighting and companies that
supply amenities.
o Record payments received from vendors for the site fee at the festival.

Reports Required Include

o A list of vendors and what they provide


o Ticket sales
o Profit and Loss accounts
o Total turnover for the event

The Staff

There are two directors of the company. They are the guys who make contacts with
potential clients, bands and land owners. Their main role is overall management of
the company and bringing in new business.

There are Five Marketing Agents

The Snooty Cat Page | 2


The Snooty Cat Festival Company
These people work with the directors to bring in new business as well as finding
partners to work with. They are also responsible for advertising the events.

There are ten other staff who work in the office and are responsible for the day to day
organisation of the business and the events

There are two Finance Managers who are responsible for all the accounts, takings,
expenditure and paying the staff.

Outside Database Scope

Local Authorities
Content of the advertising
Actual payment info (e.g. the database should not store credit card numbers)
Anything that would be better handled by other systems, e.g. by telephone, email or
by using a calendar or a website. It is your responsibility to scope this project and
decide what should and should not be included in the database system. This will form
part of the assumptions that you make and needs to be clearly stated.

There is not enough information here to get your requirements absolutely clear and
as you cannot ask the client you are going to have to make some assumptions about
how the system should do things and what should or should not be included. You
must document these as everyone will think different things and what I am looking for
is that your design follows your logic as stated in your assumptions.

The Snooty Cat Page | 3


The Snooty Cat Festival Company Design Decisions and Assumptions

Analysing The Snooty Cat Festival Company, I have identified the following entities.(see Figure 1).

Figure 1 - Identified entities


Festival Types – Because Snooty Cat Company organises different types of festivals, I assume that in the future they may
organise festivals, not mentioned in the brief. Therefore, the festival_type_ID it will be a foreign key in Festivals entity and the
company will have the flexibility to add new festival types over time.

First Aid – I am assuming that the arrangements for first aid will be done over the phone/email and the Snooty Cat Company just
need to record if that arrangement was made or not and the details of the arrangement are kept in a signed contract form.
Therefore, I decided to not include a First Aid entity but the arrangement to be recorded under FESTIVAL as an attribute as First
Aid Available (boolean) with the values of YES/NO. However, if more details are required to be recorded for arrangements I may
want to clarify with Snooty Cat Company.

Tickets Sale – Because the CLIENT gets the money from the tickets sales and Snooty Cat Company just facilitate the sales and
assuming that the tickets will have a series number to identify each particular ticket, I will assign a table for tickets where the sold
tickets will be recorded along with their sale price (e.g. Festival-1 were sold 320 tickets at £25 each; Festival-2 were sold 100
tickets at £18 each etc.). The payment method of tickets I am assuming will be done through a specialised website such as PayPal
or handled by a payment processing company (e.g. Sage) and Snooty Cat Company will record only the number of tickets sold per
festival In the database.

Contractors / Vendors / Suppliers / Land Owners – Over time the Snooty Cat Company may have other different types of
participants (e.g. Animators, Entertainers) not mentioned in this case study. Therefore, instead of sticking with these entities I
have decided to use one entity as Partner and one as Partner Groups, where partner_group_ID is a foreign key in Partners entity
and the company would have the flexibility to add more types of partners without need to redesign the database.

Band Payments – I am assuming that an Agent may have several bands under his/her management and they have their own
arrangements/contracts. The payment for band/s would go to the Agent rather than each band and the Agent may use their own
payment system based on what agreement they have. I would contact Snooty Cat Company to clarify who receives the payment.

Site Pitch – I am assuming that Snooty Cat Company would have digital/hard copies of the land layout and they would allocate a
predefined space (e.g. Stand A1, A2, B1, B2 etc.) at the festival for each vendor. I decided to not use Site Pitch as an entity. The
vendor location would be recorded as an attribute in a new entity Festival Details where vendors would be recorded with what
services they offer, location at the festival along with arriving and departure date/time.

Staff – I am assuming that the staff payment will be handled by the company payroll system therefore I will not include any staff
payment records.
- I am assuming that the directors will make contact with potential clients, agents and/or land owners through phone/email and
they will have their own contact details. Once an agreement of participation is made between Snooty Cat Company and client,
agent or land owner the directors will record the details in database.

Festival Advertising – They are not enough information regarding the festival advertising. I am assuming that the Marketing
Department, have own tracking methods, unless the Snooty Cat Company specifies otherwise and I would clarify with them to
include Advertising to the database.

Other – The local authority’s approval, special permits or any other contracts requirements are not specified in the case study and
they are not part of the database system.

| DBPRIN – SUBMISSION 1 Page 1 of 10


Figure 2 - Snooty Cat Festival Company ERD
| DBPRIN – SUBMISSION 1 Page 2 of 10
Data Dictionary for Snooty Cat Company database

AGENT
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_agent PK TINYINT UNSIGNED auto increment Agent ID, Auto generated
ID_partner SMALLINT UNSIGNED NOT NULL partner.ID_partner
covering_area VARCHAR(50) Area covered by the agent (e.g. International, South London etc.)

AMENITY
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_amenity PK SMALLINT UNSIGNED unsigned; auto increment; Amenity ID, Auto generated
amnity_name VARCHAR(100) NOT NULL Name of the facility available at festival
amnity _note TINYTEXT Descriptive note if is required

BAND
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_band PK SMALLINT UNSIGNED auto_increment; Band ID, Auto generated
ID_agent TINYINT UNSIGNED agent.ID_agent
b_name VARCHAR(50) NOT NULL Name of the band
b_genre VARCHAR(30) Music genre played by the band
b_members_no TINYINT(2) Number of members in the band

CLIENT
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_client PK TINYINT UNSIGNED auto_increment; Client ID, Auto generated
c_company AK VARCHAR(100) Client company name
c_name VARCHAR(20) NOT NULL First name of person of contact or individual client
c_surname VARCHAR(20) Last name of person of contact or individual client
c_address1 VARCHAR(50) NOT NULL Client address field 1
c_address2 VARCHAR(50) Client address field 2
c_postcode CHAR(8) NOT NULL Client address postcode

| DBPRIN – SUBMISSION 1 Page 3 of 10


c_city VARCHAR(30) Client address city
c_email AK VARCHAR(60) NOT NULL Client contact email address
c_phone AK VARCHAR(15) NOT NULL Client contact phone number

FESTIVAL
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_festival PK SMALLINT UNSIGNED auto_increment; Festival ID, Auto generated
ID_client TINYINT UNSIGNED NOT NULL client.ID_client
ID_festival_type TINYINT UNSIGNED festival_type.ID_festival_type
ID_amenity SMALLINT UNSIGNED amenity.ID_amenity
f_name AK VARCHAR(100) NOT NULL Name of the festival
f_date DATE NOT NULL Date of the festival
NOT NULL DEFAULT
f_first_aid ENUM('YES','NO') Arrangements for First Aid service
'NO'
f_budget DECIMAL(6,2) NOT NULL The money paid by the client per festival

FESTIVAL_TYPE
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_festival_type PK TINYINT UNSIGNED auto_increment; Festival Type ID, Auto generated
ft_name VARCHAR(100) NOT NULL Festival type name (e.g. music festival, folk festival etc.)
ft_notes TINYTEXT Descriptive note if is required

FESTIVAL_DETAILS
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_festival PK SMALLINT UNSIGNED NOT NULL festival.ID_festival
ID_venue PK TINYINT UNSIGNED NOT NULL venue.ID_venue
ID_service MEDIUMINT UNSIGNED NOT NULL service.ID_service
contract_date DATE NOT NULL Agreement date
pitch_location VARCHAR(20) Location at the event
arriving_time DATE/TIME NOT NULL Arriving date and time of service
departing_time DATE/TIME NOT NULL Departing date and time of service
fd_note TINYTEXT Descriptive note if is required

FESTIVAL_PERFORMERS

| DBPRIN – SUBMISSION 1 Page 4 of 10


PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_band PK SMALLINT UNSIGNED NOT NULL band.ID_band
ID_festival PK SMALLINT UNSIGNED NOT NULL festival.ID_festival
fp_entry_time TIME NOT NULL The time when band start performing
fp_end_time TIME NOT NULL The time when band end performing
fp_stage_time TIME Auto generated record based on the ‘end time’ – ‘entry time’
fp_notes TINYTEXT Descriptive note if is required

LANDOWNER
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_landowner PK SMALLINT UNSIGNED auto_increment; Landowner ID, Auto generated
ID_partner SMALLINT UNSIGNED NOT NULL partner.ID_partner

PARTNER
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_partner PK SMALLINT UNSIGNED auto_increment; Client ID, Auto generated
ID_partner_group TINYINT UNSIGNED NOT NULL partner_group.ID_partner_group
p_company VARCHAR(100) Client company name
p_name VARCHAR(20) NOT NULL First name of person of contact or individual client
p_surname VARCHAR(20) Last name of person of contact or individual client
p_address1 VARCHAR(50) NOT NULL Client address field 1
p_address2 VARCHAR(50) Client address field 2
p_postcode CHAR(8) NOT NULL Client address postcode
p_city VARCHAR(30) Client address city
p_email AK VARCHAR(60) NOT NULL Client contact email address
p_phone AK VARCHAR(15) NOT NULL Client contact phone number

PARTNER_GROUP
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_partner_group PK TINYINT UNSIGNED auto_increment; Partner Group ID, Auto generated
p_group_name VARCHAR(50) NOT NULL Name of the group (e.g. Vendor, Contractor, Supplier)

PAYMENT

| DBPRIN – SUBMISSION 1 Page 5 of 10


PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_payment PK MEDIUMINT UNSIGNED auto_increment; Payment ID, Auto generated
ID_partner SMALLINT UNSIGNED NOT NULL partner.ID_partner
ID_festival SMALLINT UNSIGNED NOT NULL festival.ID_festival
ID_staff TINYINT UNSIGNED NOT NULL staff.ID_staff
pmt_date DATE NOT NULL Date of the payment
pmt_amount DECIMAL (6,2) NOT NULL Amount of the payment
NOT NULL DEFAULT Payment type (e.g. a vendor “paid in” or a payment to an
pmt_type ENUM('PAYMENT','IN','OUT')
'PAYMENT' agent is “paid out”)

SERVICE
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_service PK MEDIUMINT UNSIGNED auto_increment; Service ID, Auto generated
ID_partner SMALLINT UNSIGNED NOT NULL partner.ID_partner
service_name VARCHAR(50) NOT NULL Name of the service (e.g. Lights, Musical Instruments etc)
service_price DECIMAL(6,2) NOT NULL Price of the service
service_description TEXT Description of the service

STAFF
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_staff PK TINYINT UNSIGNED auto_increment; Staff ID, Auto generated
ID_staff_role TINYINT UNSIGNED NOT NULL staff_role.ID_staff_role
s_name VARCHAR(20) NOT NULL Staff personel first name
s_surname VARCHAR(20) NOT NULL Staff personel last name
s_address1 VARCHAR(50) NOT NULL Staff personel address field 1
s_address2 VARCHAR(50) NOT NULL Staff personel address field 2
s_postcode CHAR(8) NOT NULL Staff personel address postcode
s_city VARCHAR(30) NOT NULL Staff personel address city
s_email VARCHAR(60) NOT NULL Staff personel contact email address
s_phone VARCHAR(15) NOT NULL Staff personel contact phone number

STAFF_ROLE
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_staff_role PK TINYINT UNSIGNED auto_increment; Staff role ID, Auto generated

| DBPRIN – SUBMISSION 1 Page 6 of 10


s_role_name VARCHAR(20) NOT NULL Name of the role (e.g. Management, Marketing etc.)
STAFF_TASK
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_task PK MEDIUMINT UNSIGNED auto_increment; Task ID, Auto generated
ID_festival SMALLINT UNSIGNED NOT NULL festival.festival_ID
ID_staff TINYINT UNSIGNED NOT NULL staff.staff_ID
task_name VARCHAR(50) NOT NULL Name of the task (e.g. Flyer design, Contact Security)
task_date DATE Date when task need to be done
task_time TIME Time when task need to be done
task_details TEXT Extra details about the task
NOT NULL DEFAULT
task_completed ENUM('YES','NO') Marking task as complete.
'NO'

TICKET_SALE
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_sale PK MEDIUMINT UNSIGNED auto_increment; Sale of tickets ID, Auto generated
ID_festival SMALLINT UNSIGNED NOT NULL festival.ID_festival
ticket_start_series VARCHAR(20) NOT NULL Starting series number of tickets (e.g. F123456)
ticket_end_series VARCHAR(20) NOT NULL Ending series number of tickets (e.g. F654321)
ticket_sold SMALLINT UNSIGNED NOT NULL Number of tickets sold
ticket_price DECIMAL (4,2) NOT NULL Price of the tickets

VENUE
PK
Attribute Name Data Type & Size Domains and constraints FK Reference Description
AK?
ID_venue PK MEDIUMINT UNSIGNED auto_increment; Venue ID, Auto generated
ID_landowner SMALLINT UNSIGNED NOT NULL landowner.ID_landowner
venue_name VARCHAR(50) NOT NULL Name of the venue
venue_address1 VARCHAR(50) NOT NULL Venue location field 1
venue_address2 VARCHAR(50) Venue location field 2
venue_postcode CHAR(8) NOT NULL Venue location postcode
venue_city VARCHAR(30) Venue location city
venue_capacity SMALLINT UNSIGNED NOT NULL Total of people capacity of venue
venue_rent_price DECIMAL(5,2) NOT NULL The price of renting the venue

| DBPRIN – SUBMISSION 1 Page 7 of 10


| DBPRIN – SUBMISSION 1 Page 8 of 10
Normalisation of the tables

| DBPRIN – SUBMISSION 1 Page 9 of 10


| DBPRIN – SUBMISSION 1 Page 10 of 10
The Snooty Cat Festival Company Database Security
Security

In our digital era probably the security term, is one of the most used terms. Security can vary from a country
security to a device security or personal security and under the broad term of security databases are included as well.

The most used term is hacking but it is only one of the many security
risks that a database is exposed along with physical damage, data corruption,
natural disasters, hardware failure, 3rd party integrated software, users (regular
users and administrators) or even design flaws. Some of the results of the security
breaches of a database would be: loss of privacy, integrity, availability,
confidentiality or theft and fraud (Connolly & Begg, 2015).

As any other database system, Snooty Cat Festival Company (I will refer
from now on as SCFC) database is vulnerable to many security issues, and as any Figure 1 - General type of users
other organisation these potential threats must be taken into account.

Unauthorised Access

Probably unauthorised access to a database is the starting point of any security issue. The access to the SCFC
database needs to be limited and only the person with the right authorisation needs to be able to input/edit or delete
data. We must not confuse the authentication with authorization. Authentication will allow the user to login to the
system where authorization will constrain what to access into the system (privileges). Privileges are issued via the
GRANT command and are taken away via the REVOKE command where DENY will forbidden access to a certain
privilege and the group privileges are controlled through ROLES (reduce security maintenance by not having to grant
explicit privileges directly to a user but to a group). As an example related to the SCFC database would be the staff
users (STAFF table). A staff with the accountant role (defined by STAFF_ROLE table), it should not have access to
input data to the festivals (FESTIVAL table) but will have access to generate invoices (PAYMENT table). SCFC
database users’ needs to be given specific roles and privileges necessary to accomplish their job but they should not
have access that extends beyond the scope of his or her job duties also known as “principle of least privilege”. I must
mention a common “mistake” done by the DBAs is the fact that, when a user no longer requires access to the database,
the account remain active longer than necessary. Therefore, the user account should be deleted/disabled immediately.
For SCFC database only the DBA should have direct access to the database root and run queries. The database
root access must be protected with a password where all other users should access the database inputs/outputs through
forms and reports.
As an extra measure of control and prevention, for the database a database connection session should be
recorded (creating a new table with a user session) and “DBA can use database roles and resource limits to minimize
the impact of rogue users in the system” (Coronel & Morris, 2017).

Note: For a full understanding of user roles in the company and what they need to access and what not, I need to
clarify with Snooty Cat Company.

Backup & Recovery

As any other digital system databases are vulnerable to data corruption or data loss (due to various reasons
such as hardware failure, user mishandling or natural disasters). Therefore, a Backup & Recovery policy must be in
place. This policy must be enforced by SCFC if the database is located on their facility (or if they are responsible for
database deployment/maintenance) otherwise the company, handling the database service; (please see a draft of a
proposed policy as Appendix B). As a DBA I must consider all the time that the data loss may be total, therefore all
data must be recovered in full at any time. This will include regular backups policies and off-site storage location. In
my opinion, for the SCFC database a daily backup will probably be enough, but with databases running millions of
queries per second (e.g. Amazon DB) a real-time backup is required. The backup procedure can include a full backup
(a complete copy of entire database, ensuring a full recovery of all data after a database integrity failure or physical
disaster), an incremental backup (backup only of data changed from last complete or incremental backup) and a
concurrent backup (similar with real time backup, where the backup is take place when one or more users are
working on the database) (Coronel & Morris, 2017). The backups must be performed at regular intervals and as a note
it worth to be mentioned that the backed-up data must be regularly checked for data corruption and if they can be used
at any time.

| DBPRIN – SUBMISSION 2 Page 1 of 7


Encryption

Any data in a database should be secured using a combination of public, private, and symmetric keys to
encrypt and decrypt data and the encryption can be implemented at different levels (tables, columns, rows and cells)
(Hwang & Yang, 1997). However, we must note that it may be a degradation in performance because of the time
taken to decode it, but for database backup I would recommend a full encryption. One of the sensitive information in
SCFC database are the financial information therefore, the
[FESTIVAL<budget>]; [PAYMENT<pmt_ammount>] must be
encrypted at and only the users with appropriate authorisation will be
able to see that particular information (e.g. staff from finance dept.). A
new USER table will contain the user’s login credentials along with
their passwords (a password attribute) and this field needs to be stored
Figure 2 - MariaDB password Encryption Example
as one-way hashing algorithm (e.g. for MariaDB would be
PASSWORD() function) (MariaDB, n.d.).
A more complex way of encryption would be a full level database encryption supported by many vendors but
like I previous said this will have a big impact over performance. Each vendor has own syntaxes for encryption and a
good understanding of the those is a must.

SQL Injections

An SQL injection usually is performed through a web application with a connection to the database, by
inputting the malicious code into user input field and executed in the database. The first step to tackle an sql injection
threat is to ensure that the application validates data before submitting to the database. In order to increase security
against sql injections, for SCFC database two techniques must be combined: validation (to check if the input meets
criteria) and sanitization (modify the input to ensure that is valid). Oracle states that an effective defence against sql
injections is a must “to avoid SQL injection, all inputs that are to be concatenated in dynamic SQL must be correctly
filtered and sanitized” (Oracle Corporation, n.d). For SCFC database as an example would be to validate that the
postcodes with the specific UK postcodes format. Other examples are to convert the single string (') to double quotes
(") before inserting any information to database, in FESTIVAL table as f_date, no backdate of current date can be
inserted, or the f_budget attribute will validate positive integer inputs where any string input consists only of the digits
0 through 9.
In order to reduce the risk of SQL injections as much as possible a thigh collaboration between the DBA,
application developer and network administrator is a must, for a bespoke configuration, form validations, input masks
and system compatibility.
Note: For a summary of the general security vulnerabilities and the typical countermeasure please see Appendix A.

Web Database

Three-tier client server architecture (Figure 3) is composed of 3 tiers:

• Tier1 – Presentation (user interface layer - runs on the client/end


user). In this layer end-user is available to request data and the
data are returned to the user.
• Tier2 - Business logic and data processing logic, layer (runs on a
server and often is called application server or web server). This
layer handles user requests, intermediate rules and constraints and
forward to the 3rd layer, and when the results are received from
3rd layer, results are pushed back to the user in first layer.
• Tier3 – Database – (data base access and data validation, stores
data required by middle layer, also known as database server)

The 3 tier client server architecture is a scalable architecture and


each of the layers can potentially run on different platform and enhance Figure 3 - Three-tier architecture (Abstract
representation)
security because the client cannot directly access the database server but
only through the application server. Some of the advantages are app maintenance centralized, modify or replace a
layer without affecting others (Foster & Godbole, 2016).

| DBPRIN – SUBMISSION 2 Page 2 of 7


The ANSI/SPARC (American National Standard
Institute/Standard Planning and Requirements Committee) is a theoretical
abstract design (Figure 6) for a DBMS. The concept states that all users
should be able to access same data but have different customized view of
the data. The views are independent and changes to one view should not
affect others. Users no need to know any details about physical database
storage and this structure could be changed without affecting the user
views. The internal storage structure of database should not affecting
changes made to logical structure of database ( Kishansing & Sagar,
2014).
It contains 3 levels, (External Level describes the different views
needs to be relevant to a particular user; Conceptual Level describes what
data is stored in database and the relationships among the data; Internal
Level describes how the data is stored in the database and physical
representation of database). In other words, this concept breaks down the
database accessibility in 3 categories, according to its structure, use and
Figure 6 - ANSI-SPARC Three-Level
the roles played by DBA, designers and end users. Architecture
Even if ANSI/SPARC is a conceptual model the core principles
are reflected in 3-tier client server architecture. External Level describes the view of one or several users on the data in
the Tier 1 and irrelevant data for that particular user(s) are hidden; Conceptual Level establishes the entities, data type,
relationships and integrity conditions. This conceptual level blend the Tier 2 and Tier 3 by concealing the physical
memory structure and logical one. Internal Level describes the physical memory structure of the database present in
Tier 3.
The database schema provide overall description of database structure (not actual data) and each level has
own schema (Table 1).

Table 1 - ANSI/SPARCC Schema


The major objective of the three-level architecture is to provide data independence, which means the
uppermost level is unaffected by changes in the lowest level.

Snooty Cat Company Mock-ups

Figure 5 - Add a new festival form mock-up Figure 5 - Financial report with profit/loss calculation

| DBPRIN – SUBMISSION 2 Page 3 of 7


Notes:
New Type button will open a new form to add a new festival type in FESTIVAL_TYPE table if it is not already
present in the database (available through dropdown menu).
Add Client button will open a new form to add a new client to CLIENT table if the client doesn’t exist in the
database.
Add Festival Details button will open a new form in order to add all festival details. However, the festival
details form it cannot be opened from this form until the new festival is saved to the database.
The report is based on the difference between FESTIVAL [festival_budget] and PAYMENTS, after the
[pmt_amount] in/out calculation was made.

Professional, Legal and Ethical Issues

Many of the legal issues faced as a DBA involve data protection


and privacy. Breaching the legal aspect of data protection entails a
professional and ethical issue as well. My duty as DBA is my
responsibility to follow the rules stated in Data Protection Act 1998
(Figure 7). However, I must ensure that I follow and implement future
changes in legislation such as incoming in force EU General Data
Protection Regulation (EUGDPR, n.d.).

As a professional I endeavour to understand the business model,


rules, how the SCFC interacts with its clients at every step of the way in
order to be able to offer unbiased and viable solutions for any issue that
may occur. It is my responsibility as a professional to be up to date with
latest technologies and suggest improvements where are available.

As a DBA at the Snooty Cat Company, following and applying


ethical and moral obligations will ensure the trust and confidence of users, Figure 7- Core principles of DPA 1998
clients and any other parties involved. The protection of the stakeholders (GOV.UK, n.d.)
should be my primary concern. Just briefly to enumerate some of my
moral obligations: to reduce the effort of collecting repeated and unnecessary collection of data about users, use data
appropriately (e.g. not to sell for profit), to ensure stakeholders continued access to their information, to not promise
more than I can deliver, to not support contractor X, just because I know him and should teach and share my expertise
in order to help to grow the collective knowledge base.

| DBPRIN – SUBMISSION 2 Page 4 of 7


References
Kishansing, D., & Sagar, S. M. (2014). Study Of The ANSI/SPARC Architecture. International Journal of Modern Trends in
Engineering and Research, 22-30.

Connolly, T., & Begg, C. (2015). Database Systems: A Practical Approach to Design, Implementation and Management. Essex:
Pearson Education Limited.

Coronel, C., & Morris, S. (2017). Database Systems: Design, Implementation and Management (12th Edition). Boston: Cengage.

EUGDPR. (n.d.). The EU General Data Protection Regulation . Retrieved from eugdpr.org:
https://www.eugdpr.org/eugdpr.org.html

Foster, E. C., & Godbole, S. (2016). Database Systems: A Pragmatic Aproach (Second Edition). New York: Apress.

GOV.UK. (n.d.). Data protection. Retrieved from gov.uk: https://www.gov.uk/data-protection

Hwang, M.-S., & Yang, W.-P. (1997). Multilevel secure database encryption with subkeys. Data&Knowledge Engineering, 117-
131. Retrieved from http://isrc.asia.edu.tw/www/myjournal/P007.pdf

MariaDB. (n.d.). PASSWORD. Retrieved from mariadb.com: https://mariadb.com/kb/en/library/password/#syntax

Netsparker. (n.d). What is the SQL Injection Vulnerability & How to Prevent it? Retrieved from Netsparker:
https://www.netsparker.com/blog/web-security/sql-injection-vulnerability/#PreventingSQL

Oracle Corporation. (n.d). What Is Input Validation and Sanitization? Retrieved from Oracle.com:
http://download.oracle.com/oll/tutorials/SQLInjection/html/lesson1/les01_tm_ovw3.htm

| DBPRIN – SUBMISSION 2 Page 5 of 7


Appendixes

Appendix A - Security vulnerabilities of system components and typical protective measures

| DBPRIN – SUBMISSION 2 Page 6 of 7


Appendix B - Draft of Snooty Cat Data Backup and Recovery Policy

| DBPRIN – SUBMISSION 2 Page 7 of 7


Table of contents

1 agent Page number: 2


2 amenity Page number: 3
3 band Page number: 4
4 client Page number: 5
5 festival Page number: 6
6 festival_details Page number: 7
7 festival_performers Page number: 8
8 festival_type Page number: 9
9 landowner Page number: 10
10 partner Page number: 11
11 partner_group Page number: 12
12 payment Page number: 13
13 service Page number: 14
14 staff Page number: 15
15 staff_role Page number: 16
16 staff_task Page number: 17
17 ticket_sale Page number: 18
18 venue Page number: 19
19 Relational schema Page number: 20
1 agent

Creation: Apr 05, 2018 at 08:01 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_agent int(11) No auto_increment


id_partner int(11) No -> partner.id_partner
ON UPDATE CASCADE
ON DELETE NO_ACTION
2 amenity

Creation: Apr 05, 2018 at 08:02 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_amenity int(11) No auto_increment


amnity_name varchar(100 No
)
amnity_note tinytext Yes NULL
3 band

Creation: Apr 05, 2018 at 08:03 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_band int(11) No auto_increment


id_agent int(11) Yes NULL -> agent.id_agent
ON UPDATE CASCADE
ON DELETE NO_ACTION
band_name varchar(50) No
band_genre varchar(50) Yes NULL
band_members int(2) Yes NULL
No
4 client

Creation: Apr 05, 2018 at 08:03 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_client int(11) No auto_increment


client_company varchar(100 Yes NULL
)
client_name varchar(20) No
client_surname varchar(20) No
client_address1 varchar(50) No
client_address2 varchar(50) Yes NULL
client_postcode char(8) No
client_city varchar(30) Yes NULL
client_email varchar(60) No
client_phone varchar(15) No
5 festival

Creation: Apr 05, 2018 at 03:06 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_festival int(11) No auto_increment


id_client int(11) Yes NULL -> client.id_client
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_festival_type int(11) Yes NULL ->
festival_type.id_festival_type
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_amenity int(11) Yes NULL -> amenity.id_amenity
ON UPDATE CASCADE
ON DELETE NO_ACTION
festival_name varchar(100 No
)
festival_date date No
festival_faid enum('YES', No NO
'NO')
festival_budget decimal(8,0) UNSIGNED No
6 festival_details

Creation: Apr 09, 2018 at 06:11 AM

Column Type Attributes Null Default Extra Links to Comments MIME

id_festival int(11) No -> festival.id_festival


ON UPDATE CASCADE
ON DELETE NO_ACTION
id_venue int(11) No -> venue.id_venue
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_service int(11) No -> service.id_service
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_partner int(11) No -> partner.id_partner
ON UPDATE CASCADE
ON DELETE NO_ACTION
contract_date date No
pitch_location varchar(20) Yes NULL
time_arr time No
time_dept time No
fd_note text Yes NULL
7 festival_performers

Creation: Apr 06, 2018 at 09:51 AM

Column Type Attributes Null Default Extra Links to Comments MIME

id_band int(11) No -> band.id_band


ON UPDATE CASCADE
ON DELETE NO_ACTION
id_festival int(11) No -> festival.id_festival
ON UPDATE CASCADE
ON DELETE NO_ACTION
fp_time_entry time No
fp_time_end time Yes NULL
fp_stage_time time Yes NULL
fp_note text Yes NULL
8 festival_type

Creation: Apr 05, 2018 at 08:04 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_festival_type int(11) No auto_increment


ft_name varchar(100 No
)
ft_note text Yes NULL
9 landowner

Creation: Apr 05, 2018 at 08:05 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_landowner int(11) No auto_increment


id_partner int(11) No -> partner.id_partner
ON UPDATE CASCADE
ON DELETE NO_ACTION
10 partner

Creation: Apr 05, 2018 at 08:05 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_partner int(11) No auto_increment


id_partner_grou int(11) No -> partner_group.id_partner_g
p roup
ON UPDATE CASCADE
ON DELETE NO_ACTION

partner_compa varchar(100 Yes NULL


ny )
partner_name varchar(20) No
partner_surnam varchar(20) No
e
partner_addres varchar(50) No
s1
partner_addres varchar(50) Yes NULL
s2
partner_postco char(8) No
de
partner_city varchar(30) Yes NULL
partner_email varchar(60) No
partner_phone varchar(15) No
11 partner_group

Creation: Apr 05, 2018 at 08:06 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_partner_grou int(11) No auto_increment


p
partner_group_ varchar(50) No
name
12 payment

Creation: Apr 05, 2018 at 08:06 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_payment int(11) No auto_increment


id_partner int(11) No -> partner.id_partner
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_festival int(11) No -> festival.id_festival
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_staff int(11) No -> staff.id_staff
ON UPDATE CASCADE
ON DELETE NO_ACTION
pmt_date date No
pmt_amount decimal(8,2) No
pmt_type enum('Paym No
ent IN',
'Payment
OUT')
13 service

Creation: Apr 05, 2018 at 08:06 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_service int(11) No auto_increment


id_partner int(11) No -> partner.id_partner
ON UPDATE CASCADE
ON DELETE NO_ACTION
service_name varchar(50) No
service_price decimal(6,2) No
service_descript text Yes NULL
ion
14 staff

Creation: Apr 05, 2018 at 08:07 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_staff int(11) No auto_increment


id_staff_role int(11) No -> staff_role.id_staff_role
ON UPDATE CASCADE
ON DELETE NO_ACTION
staff_name varchar(20) No
staff_surname varchar(20) No
staff_address1 varchar(50) No
staff_address2 varchar(50) Yes NULL
staff_postcode char(8) No
staff_city varchar(30) Yes NULL
staff_email varchar(60) No
staff_phone varchar(15) No
15 staff_role

Creation: Apr 05, 2018 at 08:07 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_staff_role int(11) No auto_increment


staff_role_name varchar(20) No
16 staff_task

Creation: Apr 05, 2018 at 08:07 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_task int(11) No auto_increment


id_festival int(11) Yes NULL -> festival.id_festival
ON UPDATE CASCADE
ON DELETE NO_ACTION
id_staff int(11) No -> staff.id_staff
ON UPDATE CASCADE
ON DELETE NO_ACTION
task_name varchar(50) No
task_date date Yes NULL
task_time time Yes NULL
task_details text Yes NULL
task_completed enum('YES', Yes NULL
'NO')
17 ticket_sale

Creation: Apr 05, 2018 at 08:07 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_sale int(11) No auto_increment


id_festival int(11) No -> festival.id_festival
ON UPDATE CASCADE
ON DELETE NO_ACTION
ticket_series_st varchar(20) Yes NULL
art
ticket_series_en varchar(20) Yes NULL
d
ticket_sold int(10) UNSIGNED No
ticket_price decimal(5,2) UNSIGNED No
18 venue

Creation: Apr 05, 2018 at 08:08 PM

Column Type Attributes Null Default Extra Links to Comments MIME

id_venue int(11) No auto_increment


id_landowner int(11) No -> landowner.id_landowner
ON UPDATE CASCADE
ON DELETE NO_ACTION
venue_name varchar(50) No
venue_address varchar(50) No
1
venue_address varchar(50) Yes NULL
2
venue_city varchar(30) No
venue_postcod char(8) No
e
venue_capacity smallint(11) UNSIGNED No
venue_rent_pric decimal(7,2) UNSIGNED No
e
1 /*SnootyCat Database queries*/
2 /*
3 --NOTE: All ID's are just for demonstration comparation... They are not really required for the business.
For an nice layout rows output, the below query can be used. Using SET will insert a new column with
any given name (e.g. 'No') and all the records will be numbered from 1 to N. This is available only for
current session.
4 ==================
5 SET @No=0;
6 SELECT
7 @No:=@No+1 AS No
8 =================
9 */
10
11
12 /*=====================Q1============================*/
13 /*
14 --Total price for the sold tickest along with the Festival Name, Client Company and Person of Contact,
total no of the tickes sold and price per ticket. This query is for all festivals but it can be adjusted for
specific festival or criteria using WHERE clause.
15 */
16 SELECT
17 festival.id_festival AS ID,
18 festival.festival_name AS `Festival Name`,
19 festival_type.ft_name AS `Festival Type`,
20 festival.festival_date AS Date,
21 client.client_company AS `Client Company`,
22 CONCAT(client.client_name, ' ', client.client_surname) AS `Person of Contact`,
23 ticket_sale.ticket_sold AS `No of Tickets`,
24 CONCAT('£ ', FORMAT(ticket_sale.ticket_price, 2)) AS `Ticket Price`,
25 CONCAT('£ ', FORMAT(ticket_sale.ticket_sold * ticket_sale.ticket_price, 2)) AS `Total
Amount`
26 FROM ticket_sale
27 INNER JOIN festival
28 ON ticket_sale.id_festival = festival.id_festival
29 INNER JOIN client
30 ON festival.id_client = client.id_client
31 INNER JOIN festival_type
32 ON festival.id_festival_type = festival_type.id_festival_type
33 /*WHERE festival.id_festival = 1*/
34 GROUP BY festival.id_festival;
35
36
37 /*=====================Q2============================*/
38 /*
39 --Return the performing bands for a given festival along with their entry time, end time and time on stage
ordered by time_entry
40 */
41
42 SELECT
43 f.id_festival AS ID,
44 f.festival_name AS `Festival Name`,
45 f.festival_date AS Date,
46 band.band_name AS `Band Name`,
47 band.band_genre AS Genre,
48 DATE_FORMAT(festival_performers.fp_time_entry, '%H:%i') AS `Entry Time`,
49 DATE_FORMAT(festival_performers.fp_time_end, '%H:%i') AS `End Time`,
50 DATE_FORMAT(festival_performers.fp_stage_time, '%H h %i min') AS `Time On Stage`,
51 festival_performers.fp_note AS Notes
52 FROM festival_performers
53 INNER JOIN festival f
54 ON festival_performers.id_festival = f.id_festival
55 INNER JOIN band
56 ON festival_performers.id_band = band.id_band
57 WHERE f.id_festival = 1
58 GROUP BY festival_performers.fp_time_entry;
59
60
61 /*=====================Q3============================*/
62 /*
63 --Select staff tasks for a given festival where the task wasn't completed.
64 */
65
66 SELECT
67 f.id_festival AS ID,
68 f.festival_name AS `Festival Name`,
69 f.festival_date AS Date,
70 CONCAT(staff.staff_name, ' ', staff.staff_surname) AS `Staff Name`,
71 staff_role.staff_role_name AS Role,
72 staff_task.task_name AS `Task Name`,
73 staff_task.task_date AS `Assigned Date`,
74 DATE_FORMAT(staff_task.task_time, '%H : %i') AS `Assigned Time`,
75 staff_task.task_completed AS Completed,
76 staff_task.task_details AS Details
77 FROM staff_task
78 INNER JOIN festival f
79 ON staff_task.id_festival = f.id_festival
80 INNER JOIN staff
81 ON staff_task.id_staff = staff.id_staff
82 INNER JOIN staff_role
83 ON staff.id_staff_role = staff_role.id_staff_role
84 WHERE f.id_festival = 1
85 AND staff_task.task_completed = 'NO' \G
86
87 /*NOTE: Use \G for vertical display if the rows are too long and break the layout*/
88
89
90 /*=====================Q4============================*/
91 /*
92 -- A list of al vendors (partenrs) with the name, address, contact details, service(s) they provice and price
per service, sorted ASC on service name.
93 */
94
95 SELECT DISTINCT
96 partner.id_partner AS ID,
97 partner_group.partner_group_name AS `Group`,
98 CONCAT(partner.partner_company, ' ', partner.partner_name, ' ', partner.partner_surname)
AS Partner,
99 CONCAT(partner.partner_address1, ' ', partner.partner_address2, ' ', partner.partner_city, ' ',
partner.partner_postcode, ' ') AS Address,
100 CONCAT(partner.partner_email, ' | ', partner.partner_phone) AS Contact,
101 service.service_name AS Service,
102 CONCAT('£ ', FORMAT(service.service_price, 2)) AS Price,
103 service.service_description AS `Service Description`
104 FROM service
105 INNER JOIN partner
106 ON service.id_partner = partner.id_partner
107 INNER JOIN partner_group
108 ON partner.id_partner_group = partner_group.id_partner_group
109 ORDER BY Service;
110
111
112 /*=====================Q5 - Buildup====================*/
113 /*
114 --All payment for a given festival ID (IN/OUT)
115 */
116
117 SELECT
118 festival.id_festival AS ID,
119 festival.festival_name AS `Festival Name`,
120 festival.festival_budget AS `Festival Budget`,
121 payment.pmt_amount AS Payment,
122 payment.pmt_type AS `Payment Type`
123 FROM payment
124 INNER JOIN festival
125 ON payment.id_festival = festival.id_festival
126 WHERE festival.id_festival = 1
127 ORDER BY `Payment Type`;
128
129 /*
130 --Total payment OUT for a given festival
131 */
132
133 SELECT
134 festival.id_festival AS ID,
135 festival.festival_name AS `Festival Name`,
136 payment.pmt_type AS `Payment Type`,
137 payment.pmt_amount AS Amount
138 FROM payment
139 INNER JOIN festival
140 ON payment.id_festival = festival.id_festival
141 /* WHERE payment.pmt_type LIKE '%OUT'; */
142 WHERE festival.id_festival = 1
143 AND payment.pmt_type LIKE '%OUT';
144
145 /*
146 --Total Payment IN for a given festival
147 */
148
149 SELECT
150 festival.id_festival AS ID,
151 festival.festival_name AS `Festival Name`,
152 payment.pmt_type AS `Payment Type`,
153 payment.pmt_amount AS Amount
154 FROM payment
155 INNER JOIN festival
156 ON payment.id_festival = festival.id_festival
157 WHERE festival.id_festival = 1
158 AND payment.pmt_type LIKE '%IN';
159
160 /*
161 --Total IN/OUT payments for all festivals (or given festival using WHERE clause).
162 */
163
164 SELECT
165 f.id_festival AS `ID`,
166 f.festival_name AS `Festival Name`,
167 f.festival_date AS Date,
168 SUM(CASE WHEN p.pmt_type = 'Payment IN' THEN p.pmt_amount ELSE 0 END) AS `TOTAL IN
`,
169 SUM(CASE WHEN p.pmt_type = 'Payment OUT' THEN p.pmt_amount ELSE 0 END) AS `TOTAL
OUT`
170 FROM festival f
171 INNER JOIN payment p
172 ON p.id_festival = f.id_festival
173 /* WHERE f.id_festival = 1 */
174 GROUP BY f.id_festival;
175
176 /*=====================Q5====================*/
177 /*
178 --Total profit and loses for all festivals (or a given festival) calculating after this formula [BUDGET +
PAYMENT IN - PAYMENT OUT = TOTAL PROFIT]
179 */
180
181 SELECT
182 f.id_festival AS ID,
183 f.festival_name AS `Festival Name`,
184 f.festival_date AS Date,
185 CONCAT('£ ', FORMAT(f.festival_budget, 2)) AS Budget,
186 CONCAT('£ ', FORMAT(SUM(CASE WHEN p.pmt_type = 'Payment IN' THEN p.pmt_amount ELSE
0 END), 2)) AS `TOTAL IN`,
187 CONCAT('£ ', FORMAT(SUM(CASE WHEN p.pmt_type = 'Payment OUT' THEN p.pmt_amount
ELSE 0 END), 2)) AS `TOTAL OUT`,
188 CONCAT('£ ', FORMAT(f.festival_budget
189 + ROUND(SUM(CASE WHEN p.pmt_type = 'Payment IN' THEN p.pmt_amount ELSE 0 END), 2)
190 - ROUND(SUM(CASE WHEN p.pmt_type = 'Payment OUT' THEN p.pmt_amount ELSE 0 END), 2
), 2)) AS PROFIT
191 FROM festival f
192 INNER JOIN payment p
193 ON p.id_festival = f.id_festival
194 /*WHERE f.id_festival = 1*/
195 /*WHERE f.festival_date LIKE '2014%' */
196 /*WHERE f.festival_date < '2015-01-01' */
197 GROUP BY f.id_festival;
198
199 /*=====================Q6====================*/
200 /*
201 -- Select all services for a given festival, along with the company (partener) provinding that service,
service name, price and pitch location at the festival
202 */
203
204 SELECT
205 festival.id_festival AS ID,
206 festival.festival_name AS `Festival Name`,
207 festival.festival_date AS Date,
208 partner.partner_company AS `Company Name`,
209 CONCAT(partner.partner_name, ' ', partner.partner_surname) AS `Person of Contact`,
210 CONCAT(partner.partner_phone, ' | ', partner_email) AS `Phone & eMail`,
211 partner_group.partner_group_name AS `Services Group`,
212 service.service_name AS Service,
213 CONCAT('£ ', FORMAT(service.service_price, 2)) AS Price,
214 festival_details.pitch_location AS Pitch
215 FROM service
216 INNER JOIN partner
217 ON service.id_partner = partner.id_partner
218 INNER JOIN partner_group
219 ON partner.id_partner_group = partner_group.id_partner_group
220 INNER JOIN festival_details
221 ON festival_details.id_service = service.id_service
222 AND festival_details.id_partner = partner.id_partner
223 INNER JOIN festival
224 ON festival_details.id_festival = festival.id_festival
225 WHERE festival.id_festival = 1
226 ORDER BY ID;
227
228 /*=====================Q7====================*/
229 /*
230 --Select venue(s) with a capacity >= to 3000 places and a renting price <= £20.0000;
231 */
232
233 SET @No = 0;
234 SELECT
235 @No := @No + 1 AS No,
236 venue.id_venue AS ID,
237 venue.venue_name AS `Venue Name`,
238 venue.venue_city AS `Venue City`,
239 venue.venue_capacity AS `Venue Capacity`,
240 CONCAT('£ ', FORMAT(venue.venue_rent_price, 2)) AS `Venue Rent Price`,
241 partner.partner_company AS Company,
242 CONCAT(partner.partner_name, ' ', partner.partner_surname) AS `Person of Contact`,
243 CONCAT(partner.partner_email, ' | ', partner.partner_phone) AS `Contact Details`
244 FROM landowner
245 INNER JOIN partner
246 ON landowner.id_partner = partner.id_partner
247 INNER JOIN venue
248 ON venue.id_landowner = landowner.id_landowner
249 WHERE venue.venue_capacity >= 3000
250 AND venue.venue_rent_price <= 20000;

Вам также может понравиться