Full transcript
0:00in this video we are going to talk about
0:03databases when you're dealing with
0:05backend systems interacting and handling
0:07databases is one of the most important
0:10and one of the most frequent operation
0:12that you're going to perform so
0:15understanding all the concepts
0:17surrounding it is crucial to be
0:19efficient in your job so let's start
0:21with the question why why do we need
0:24databases in the first place now at its
0:27core a database is simp simply a way to
0:31persist information across different
0:33different sessions to talk in a very
0:36high level and what that means is and
0:39persistence basically means storing data
0:41in a way so that it survives even after
0:44the program that created it has been
0:47stopped so for example think of your
0:50to-do list app right you add an entry
0:54and you can check off all the task that
0:57you have already finished etc etc like
0:59that's the basic functionality and
1:01expectation from a to-do app now when
1:04you do some operation when you create an
1:06item or you when check off an item and
1:08you close the app and when you open it
1:10again you find all the information the
1:12state of the data that you left it it's
1:15the same when you visit again when you
1:18come back to the app so that's what we
1:21mean when you say persistence the
1:24information has to be there in the same
1:27expected
1:28State even after a considerable amount
1:31of time has passed or across different
1:34different physical locations right
1:36that's what we mean by persistence if
1:38you did not have persistence every time
1:40you open that app You' have to create
1:43new to-do list items and You' lose all
1:45your progress whatever task you had
1:48created previously etc etc right
1:50persistence is a very important thing
1:52and we use it in our day-to-day lives a
1:55lot now what is a database when what do
1:59we mean
2:00when we say the word database the term
2:05database is surprisingly very very Broad
2:09in the simplest sense any kind of
2:12structured any kind of structured
2:14storage can be considered as a database
2:17for example you have a smartphone and in
2:21your phone you have a contact list right
2:24of different different people and that
2:27list can be considered as a database
2:30in the same way if you are a developer
2:33you must be familiar with the concept of
2:35local storage uh which is offered by
2:38every browser so we can check that out
2:41right now if we open this the developer
2:44tools and when we go application and we
2:47can check the local storage and it has
2:49some entries right since we are using
2:51this website called xcal draw the
2:53website has stored some entries in the
2:57format of key Value Store it also has a
3:00session storage also has a cookie
3:02storage etc etc right all these
3:04different different types of storage
3:06mechanisms they are also considered as a
3:09database and even if you take a simple
3:11text file where you just jot down notes
3:15and you can refer to those notes later
3:18on even that can be considered as a very
3:21very basic database so if you try to
3:25derive the patterns from all these
3:27examples database basically means
3:30is some kind of system some kind of
3:32persistent system which offers ways to
3:35create read update and delete data from
3:38it right that's a very basic and high
3:41level example of database which is not
3:44limited to what we mean when we say
3:46database in the context of backend
3:48systems database is a very generic term
3:51which means a persistence layer which
3:54provides operations of crud create read
3:56delete and update but when we say
4:00database in the context of backend
4:02systems in the context of servers right
4:05in typical developer context when we
4:09mention database there what we mean is
4:13disk based databases disk based right
4:16and by dis I mean hard disk it can be
4:19HDD ssds or whatever modern technology
4:22of storage we have available but why dis
4:26storage why dis based databases because
4:30disk storage whether it's a traditional
4:32hard drive or a modern solid state drive
4:35or also known as SSD is relatively cheap
4:39when compared to other means of storage
4:42for example when we consider Ram which
4:44is also considered as a main memory or
4:47the primary memory when we take into
4:49account our CPU unit right if you're
4:52from a computer science background you
4:53must have known that we have a CPU unit
4:56which can access the primary memory and
5:00it can also access the secondary memory
5:02which we also call as dis based memory
5:05right which uses either a hard drive or
5:08a SSD now Ram is very fast it's called
5:12main memory and it is very very fast as
5:15compared to the dis based alternative
5:18but the problem is Ram based storage
5:23it's relatively costly and we don't have
5:27as much Supply as you do when it comes
5:30to dis based so if you check the
5:33configuration of your system whether it
5:35is a Windows Bas Linux Mac does not
5:37matter if you check the configuration of
5:39your system most people have something
5:42like 8 GB Ram or 16 GB Ram or 32 GB Ram
5:46or if you are on the higher end of the
5:49consumer you must be having 64 or Max to
5:53Max 128 GB of RAM right but when it
5:56comes to hard disk when it comes to a
5:58second disc storage most people since
6:01hard discs are relatively cheap these
6:03days most people they have storage
6:06starting from 5 12 GB up to 2 TB right
6:10that's the average storage people have
6:12in their laptops in their systems right
6:15and you can see the pattern we when it
6:17comes to the storage space we have
6:20limited amount of ram we have limited
6:22amount of primary memory but we have a
6:24lot of space when it comes to displaced
6:27memory or secondary memory and trade off
6:29is RAM is very fast when it comes to
6:33data retrieval or data saving and disk
6:36based storage is relatively slow because
6:39of the way the data is stored and
6:41because of the way the data is fetched
6:44and that's the reason when we use
6:47caching mechanisms either in redis or in
6:51memory caches etc etc whenever we talk
6:53about caching we talk about storage in
6:57Ram or storage in primary memory
7:00because fetching data or saving data
7:03from primary memory from our cache is
7:06very very fast when it comes to fetching
7:08data from our databases which are disk
7:10based storages also known as secondary
7:12storage but when it comes to databases
7:15the thing that matters most is we need
7:18more space and we can do a fair amount
7:22of tradeoff when it comes to speed and
7:25that's the reason most databases at
7:27least when it comes to traditional
7:29databases like relational or non-
7:31relational databases they are based on
7:35disk based storage or secondary storage
7:38that's where they actually store the
7:39data and the format they store the data
7:42the way they store their data all the
7:43algorithm surrounding it etc etc that's
7:46a very technically deep area and we are
7:49not going to cover that in this video we
7:52just want to keep this relevant for a
7:55backend engineer right on the
7:57application Level the only thing you
7:58need to know is
8:00caching Technologies like redis Etc they
8:03store their data in primary memory or
8:05RAM and databases traditional databases
8:09like POG or mongod Debi which we'll
8:12cover next all these relational or non-
8:15relational databases they store their
8:16data in disk or secondary memory because
8:20disk based storages offer more capacity
8:23at less price but at the cost of less
8:26speed that it is clear we are talking
8:29about databases in the context of disk
8:33based storage and that too in the
8:36context of backend systems right now we
8:40come to a term which is known as dbms
8:44also known as database management system
8:46now what is a database management system
8:50just storing our data whatever data we
8:53have just storing it in some kind of dis
8:56based storage that is not enough of
8:59course we also need different different
9:01ways of retrieving that data or making
9:04changes to that data or deleting that
9:06data right all these different different
9:08operations that has to be done and that
9:11has to be done in a very efficient way
9:14since we are talking about hundreds and
9:16thousands of GBS of data right so we
9:19need these operations create read update
9:22and delete operations and that to in a
9:24very efficient manner and that's the
9:26reason we have softwares we have
9:28software systems
9:29called as dbms softwares and whose sole
9:34responsibility is to efficiently provide
9:36all these cud operations to this to the
9:40clients or to the users whoever is using
9:42it and storing that data of course they
9:45also have a lot of other
9:46responsibilities like security and
9:48scaling the database systems and load
9:51balancing etc etc right but on a very
9:54high level they have two
9:55responsibilities storing the data and
9:58providing different different operations
9:59to the client or the user primarily CED
10:02operations create read update and delete
10:05so in a way some of the responsibilities
10:08of dbms that we can point out is First
10:13Data organization they need to
10:16efficiently organize the data so that
10:18fetching updating and creating more data
10:21etc etc all these operations are
10:23efficient second access as I've already
10:26mentioned they have to provide methods
10:29to do c operations create read update
10:31and delete third Integrity now it's a
10:34technical term but what it basically
10:37means is the accuracy of the data the
10:41validity of the data we'll see what all
10:43these different different buzzwords mean
10:46when we actually go into examples so
10:49this just means the data is correct
10:52right whatever data that we are storing
10:54that data is valid that data is not
10:56corrupt so to give you a very high level
10:59example it's an e-commerce platform and
11:02we want to store all the order details
11:05of customers and each order will have
11:07some kind of payment information how
11:10much was the order etc etc right and in
11:13the database we are storing the payment
11:15amount as a number so it's the
11:18responsibility of our database
11:20management system or our dbms software
11:23to maintain the Integrity of the data so
11:26that no one can insert anything in that
11:29field if we have a payment field then
11:33for this field we want only number data
11:36Ty right we want some kind of numerical
11:40amount so someone if someone tries to
11:43store a string something like let's say
11:46something and if they try to insert it
11:49here that should fail the dbms software
11:51should not allow it because it's their
11:55responsibility to maintain the Integrity
11:57of the data the correctness of the data
11:59the validity of the data right it has a
12:01lot of meanings in a lot of contexts but
12:05this is what it means the data has to be
12:07accurate the data has to be consistent
12:09now fourth is security which basically
12:12means protecting the data from
12:14unauthorized access databases dbm
12:16softwares have different different users
12:18different different roles etc etc for
12:21the sake of protecting the access to
12:23data right so that's a very high level
12:26overview of what are the different
12:27responsibilities of database management
12:30system now here we have a question why
12:32do we need these dbms softwares why not
12:37use just simple text files or any kind
12:39of file and store all our data in text
12:42format inside it and when people were
12:45coming up with these concepts of
12:48databases or before people came up with
12:50these concepts of database management
12:52system this is how people started with
12:55they try to store all the data in text
12:58files right now the problem with storing
13:01your data in text files is there are a
13:03couple of problems first thing parsing
13:05so if we are going to store our data in
13:08a text file every time you wanted to
13:11find a specific data point let's say
13:14it's a customer database and you are
13:16storing all the details of your customer
13:18in your database inside that text file
13:21as plain text and every time you want to
13:24find a specific customer you'd have to
13:26write code application code it it can be
13:29any programming language python Java
13:31JavaScript go rust it can be any
13:34programming language you have to write
13:36code in that programming language in
13:38your application Level in your backend
13:40code to pass the text file split the
13:43lines so if we have a text file and we
13:46have different different lines you have
13:48to pass all the entries of this text
13:50file and we have to split these lines
13:53and we have to compare each field and
13:55this whole process is very slow if
13:57you're familiar with passing data from
13:59our file system in different different
14:01programming languages languages like
14:03rust are relatively faster when it comes
14:05to passing kind of uh operations but
14:09languages like JavaScript python are
14:11relatively slower as compared to rust
14:14right they are fast but compared to a
14:18highly performing language like rust
14:20they are relatively slow so if you're
14:22programming language is something like
14:24JavaScript or Ruby then you'll also face
14:28a huge performance
14:29hit right and also doing all this
14:32passsing thing is very error prone if
14:36something goes wrong you can corrupt
14:38your data you can provide wrong
14:39information to your customers etc etc
14:41like parsing itself is not an efficient
14:44solution because how slow the operation
14:47is and how error prone it is the second
14:49thing is there is no structure text
14:52files do not have a formal structure you
14:55cannot enforce that data has to be in
14:59this particular structure in this file
15:01right text files are very fluid you can
15:05store any amount of text in any format
15:08you just have to dump it there right
15:10there is no structure and that makes it
15:14very difficult to enforce consistency in
15:16data you cannot enforce something like
15:19this particular field will only have
15:22number you cannot enforce that rule
15:25right since it is all text file since it
15:27is all string it will take any kind of
15:30data and it will put it there right it
15:32cannot promise any kind of data
15:34consistency third thing concurrency by
15:37concurrency what we mean what happens if
15:40two people at the same time try to
15:43update the same taex value right whose
15:45update is going to be considered as
15:48legit and whose update is going to be
15:51going to get discarded obviously the
15:53last one who updated this text file only
15:56their update is going to persist because
15:59let's say we have a text file and we
16:02have an entry let's say amount right
16:06amount and we have something like 40 two
16:09people are trying to access it for the
16:11sake of modification they want to modify
16:13this field called amount so the first
16:15thing they will do obviously is read the
16:17file right they need to read the file
16:19before they make any changes they cannot
16:22just put some arbitary amount they want
16:24to increase the amount so one person
16:26wants to increase the amount by 20
16:28another person wants to to decrease the
16:29amount by 20 now what happens both of
16:32them read the data right both of them
16:35read the data at the same time they
16:36start their operation at the same time
16:39okay they both have the initial entry of
16:4140 so the first person they increase the
16:43amount so they do 60 and the second
16:47person they want to decrease the amount
16:49so they do it 20 and they save it now
16:52even though both of them started at the
16:54same time because it was a read
16:56operation when they save it of course
16:58there is going to be some kind of first
17:01comes first Ser kind of situation you
17:03cannot tell beforehand that this update
17:06is going to persist or this update is
17:08going to persist it all depends on what
17:10CPU cycle it is running and and thousand
17:13different parameters right so depending
17:16on the environment of the system at the
17:20end of this operation at the end of both
17:22of these operations the value it might
17:25be 60 or it might be 20 right there is
17:28no consistency here that's what you mean
17:31by concurrency when two different users
17:35try to do some kind of modification at
17:38the same time to the same data you need
17:41some kind of concurrency mechanisms
17:43inside that software inside that
17:45database software to efficiently to
17:48accurately manage the whole interactions
17:51to provide a consistent result right and
17:53a simple text file simply cannot do that
17:57so these are overall all the the
17:59challenges that people faced and if you
18:02try to do that today you'll also face
18:05the same challenges after some time
18:06after your data Grows Right and because
18:09of all these challenges because of all
18:11these limitations of Simply storing your
18:14database in a text file people came up
18:18with softwares like dbms and now that we
18:21are talking about dbms we have finally
18:23reached the stage where we can talk
18:26about different types of dbms software
18:29on a very high level we have two types
18:32the major two types one is relational
18:36and the other is the opposite non-
18:38relational relational database basically
18:40means a database system which organizes
18:43data in
18:45tables rows and columns okay and
18:51relationships between different
18:53different tables are defined using
18:56Concepts like foreign key Etc right so
18:58of the key features of relational
19:01databases data is
19:03structured and data is inserted into a
19:06database which have predefined
19:10predefined schema you cannot just
19:13arbitrarily insert or push any kind of
19:16data into your database that particular
19:19data should have a particular schema
19:21which basically means it should have a
19:24corresponding table and that table will
19:27have a very strict schema you have to
19:31beforehand Define All The Columns of a
19:35table and all the data types of those
19:37columns right everything has to be pred
19:40decided you cannot do anything on the
19:44flat it is a very strict system and
19:47because of that strict schema enforcing
19:50the advantage it offers is data
19:54Integrity which basically means at any
19:57point of time you can bet on the state
19:59of your data you know what is the data
20:04type of a particular column is what are
20:06the different relationships between
20:08different different tables and a lot of
20:10different things the data in your tables
20:12always have a consistent State they'll
20:15always have an accurate State similarly
20:18we have non- relational of and next in
20:23order to interact with this database we
20:25generally use the language SQL also
20:28known as structured query language in
20:30the same way we have non- relational
20:33databases so some examples of relational
20:36databases which you might have already
20:38heard MySQL postgress SQL Server etc etc
20:42right we have a lot of different
20:43different relational database types
20:45similarly we have non- relational you
20:47must have heard about mongod one of the
20:51most famous databases in the non-
20:53relational domain and the difference
20:56between these is while relational
20:58databases force you to have a consistent
21:02schema a very expected schema before you
21:05can put data inside your database right
21:10you have to have a predefined schema but
21:13non- relational databases do not enforce
21:15anything such as that right you can put
21:19any kind of data and two entries of a
21:24same table we don't use the term table
21:26in the non-relational domain but
21:29if you're doing a side by-side
21:30comparison then a table is called a
21:33collection in mongod right and inside a
21:36collection each entry in relational it
21:40is called rows and in non- relational or
21:42M it is called a document in relational
21:45domain each row will have the same kind
21:49of data the structure of the rows will
21:52always be the same right but in non-
21:55relational domain each document can
21:58follow different data structure okay
22:00that's the primary advantage but
22:03sometimes disadvantage when it comes to
22:05the no SQL domain the advantage is
22:07obviously it has a very flexible schema
22:10so if you're doing some kind of
22:12prototype you want to move fast you
22:14don't want to spend time figuring out
22:17your database schema enforcing the
22:19schema maintaining it etc etc then you
22:22can go with something like mongod and
22:25move very fast without thinking about
22:27your database schema you can you can
22:29push data on the Fly you can fetch any
22:31kind of data ET Etc right the
22:33flexibility can be an advantage in some
22:35scenarios so if you want to take an
22:37example let's say we have a CRM CRM also
22:40known as customer relationship
22:42management software and inside this what
22:45usually happens is it needs to maintain
22:47accurate and consistent data about
22:49customers data like contacts and all the
22:53sales opportunity details etc etc right
22:56and this data this critical data is more
22:59suited to be inside a relational system
23:01a relational database like postgress is
23:04a very good choice because it provides
23:06strong data integrity and allows for
23:08complex queries and analyze
23:10relationships between customers so a CRM
23:13system is a very good candidate when you
23:16are trying to decide between a
23:17relational database and a non-
23:19relational database in the same way if
23:23we want to find a use case for a non-
23:25relational database we can take an
23:28example like CMS also known as content
23:30management system so content Management
23:33systems are used to push content from a
23:37remote site to different different
23:39content distribution system for example
23:42let's say you have a blogging platform
23:46so every time you want to add a new
23:48article to your website you don't want
23:51to open your code base and write a new
23:53file and push it to GitHub and deploy it
23:56Etc ET right you can pull that data in
23:59your website dynamically from a Content
24:01management system it can be something
24:03like sanity Etc ET like we have a lot of
24:05cmss in the market so you can pull that
24:08data from a Content management system
24:09and you can render that data so every
24:12time you want to add a new article you
24:13just have to log into your CMS system
24:16and write that blog or article in the
24:20markdown format and save it and the next
24:23time someone refreshes your website the
24:25new article will be fetched so when you
24:28have a use case like this the content
24:31that scms needs to store that is not
24:34really structured so an article can have
24:37an image it can have a code blog it can
24:39have a YouTube embedding Etc ET like the
24:44content can be of a lot of types so a
24:48non- relational database something like
24:50the mongod makes a lot of sense when you
24:54don't know beforehand what are all the
24:56different types of data that are going
24:58to be stored here you just want to take
25:00everything and dump it here right so in
25:03these use cases mongod makes a lot of
25:05sense but even though databases like
25:09mongod they offer a lot of
25:12flexibility they can also present
25:15challenges in terms of data Integrity
25:17which is a very important concept when
25:19it comes to database systems and because
25:21they often lack the strong constraints
25:24and relationships of relational
25:27databases is EAS easier to introduce
25:29inconsistencies into the data since the
25:32schema of the data the Integrity of the
25:34data is not enforced at the database
25:37level you have to do it at the
25:39application Level which adds more
25:41complexity to your code and of course it
25:44is more error prone since application
25:46code is generally changed a lot and it's
25:49very easy to miss something right to
25:51introduce new bugs to your code base so
25:54now we have to make a choice right we
25:57are going to learn about databases and
25:59there are a lot of options in the market
26:01we have relational we have non-
26:02relational in inside relational we have
26:05MySQL we have postgress we have site and
26:08SQL Server a lot of different different
26:11products and all of them pretty much
26:13offer the same kind of features and all
26:15of them can scale when it comes to
26:18implementing in in your production
26:20systems so we have to make a choice here
26:22what database are we going to proceed
26:25with and when you have a situation like
26:27this going with postgress makes a lot of
26:29sense why a couple of reasons one it is
26:34open source and free right it is not a
26:37proprietary software it is completely
26:38open source you can go and look at the
26:41source code of the postgress even though
26:43you won't necessarily be doing that but
26:45still it is an open- Source software and
26:49a lot of companies prefer open source
26:50softwares so that they can host it they
26:53can deploy it in their own premises in
26:56their own servers etc etc right second
26:58the postgress dbms system it sticks to
27:03the SQL standard so you can take any SQL
27:06query and you can run it on a postra
27:09system and it will perform the same way
27:12it performs in a different database
27:14system like MySQL or SQL Server because
27:17the postgress database system sticks to
27:19the SQL standard so in the future if you
27:22want to migrate your database to a
27:24different system then you won't have to
27:27do a lot of work let's say you want to
27:29migrate to myql for some reason right so
27:33since postgress is SQL compli and you
27:37have written all your migration
27:39statements all your create update
27:41statements and fet statements in
27:43standard SQL format then you can just
27:46change your database and do some minor
27:48changes and you can easily switch from
27:50postgress to myql right that's one of
27:53the other reasons to go with postgress
27:56it is very easy to migrate to a
27:58different system if you need it three it
28:01is very extensible which means it offers
28:04a lot of features if you go to the
28:06postgress documentation it is around,
28:091400 pages long and it offers a lot of
28:12features pretty much covers every single
28:14use case a typical SAS might encounter
28:19right and it also has a very good
28:21extension based system so you can
28:24customize it depending on your own needs
28:26fourth it is known for its reliability
28:30and scalability and fifth I think this
28:33is the one thing that makes it easy to
28:36make the decision it has very good Json
28:39support now as we discussed just before
28:43this that one of the primary reasons to
28:46go with something like mongod a non-
28:48relational database is you can take any
28:51kind of data so when we say any kind of
28:54data we mostly mean Json any kind of
28:57Json because in Json you can Prett much
28:59store any kind of data right it can be
29:01number it can be string other Json that
29:04are embedded inside it arrays etc etc
29:07right so you can store any kind of Json
29:10as a document in a no SQL database in a
29:13mongod database in the same way since
29:16postgress offers a Json data type and it
29:18has very good indexing and query
29:21capabilities for Json Fields there is no
29:24other reason to go for a different
29:27database just for dynamic data right you
29:30can use postgress with Json fields for
29:33your needs of dynamic data as we saw in
29:35the previous examples of a Content
29:37management system if you have some kind
29:40of content that you're getting from the
29:41user and you want to save it in your
29:43database and you don't have a strict
29:46schema for that content you can go with
29:48a typical Json schema and dump whatever
29:52content that is coming from the user
29:53there and you when you want to render it
29:56you can fetch it from there and you
29:57render it right there is no need to
29:59switch to a non- relational database
30:01just for the needs of your Dynamic data
30:05right and because of all these features
30:07postgress is pretty much the number one
30:10choice when it comes to at least what I
30:12have seen a lot of startups and a lot of
30:14big companies also stick with postgress
30:17and postgress is usually their first
30:20choice and even though if you do your
30:22own research you'll find a lot of
30:24Articles where you'll see my SQL has a
30:26lot of performance benefits etc etc
30:29right but until you are serving millions
30:31of users and you want to optimize a very
30:34specific bottleneck of your application
30:36you don't really need to think about
30:38whether you should go with mycle or
30:40whether you should go with posg right
30:42since the rich set of features and the
30:45very good Json support of postgress
30:47postgress should be your first choice in
30:50pretty much all your projects and that's
30:52the reason in this video we are going to
30:55go with postgress whatever all we are
30:59going to learn about databases we will
31:01learn in the context of hress and with
31:04that I want to give a note here that
31:07there are already thousands of free
31:10resources available on YouTube elsewhere
31:13like Udi you have paid resources and you
31:16have hundreds of free resources that
31:18cover the basics of SQL and postgressql
31:22right SQL is when we say SQL it is the
31:25language that you use to query and
31:27postgress is the database system the
31:30software on which we execute our SQL
31:33queries right so there are a lot of
31:36courses pre courses available right in
31:38YouTube for both SQL and postgress right
31:42so instead of repeating the same thing
31:45instead of doing the all the create
31:47table select the basics of Order byy
31:50Group buy right all the basics of SQL
31:53and the basics of postgress again in
31:55this video we are going to save some
31:57time and we are only going to stick with
32:00some Concepts that are very relevant
32:02when it comes to backend systems and we
32:04are going to leave the basics so that
32:06you can learn it elsewhere so if you
32:09want you can pause this video right now
32:12and just search in YouTube SQL Basics
32:16you will get videos from 1 hour to 20
32:18hours and same for postgress Basics so
32:22you can choose a video according to your
32:24own
32:25Comfort what amount of comprehensiveness
32:27that you need you can watch a video of 1
32:29hour and come back to this video or you
32:32can spend a couple of days learning
32:34about SQL Basics and postgress Basics
32:36and come back to this video right so
32:39that is one of the prerequisite before
32:40you proceed to the next section so we're
32:43going to skip all the basics so that you
32:45can do your own research this is table
32:48plus it is a graphical software for
32:52interacting with your databases and it
32:55has a very modern UI fill
32:58and this is the software that I use on
33:00my day-to-day basis for all my database
33:03query operations and exploring Etc ET
33:06right so we'll be using this in this
33:09entire video to go through different
33:10different demos and to explore different
33:12different concepts now starting with
33:15what are all the different different
33:17data types that we have available in
33:19postgress I just want to bring this even
33:21though just before this I mentioned that
33:23we won't be covering the basics of
33:26postgress and basics of SQL this video
33:28but I feel this is an important piece of
33:31information that we have to cover before
33:33we proceed so that we don't have to
33:35repeat this again when we are actually
33:38talking about our backend system right
33:41now we won't be going very deep into
33:44each data type we'll just do a very high
33:46level introduction this is a create
33:48table query if you're already familiar
33:51with the SQL language then you'll
33:54recognize this this is how we create a
33:56table in any relational database whether
33:59it is POG gra myc etc etc right now we
34:02are creating a table whose name is data
34:04types demo and these are all the fields
34:07which basically means these are all the
34:09columns that are going to be in this
34:11table for each row right so starting
34:15with we have serial what does serial
34:17mean it is just an integer data type but
34:21each time we add a new entry into the
34:24table this will increment the value so
34:27by default let's say it starts with zero
34:30right the next time you insert a row and
34:33if you omit this ID field in your insert
34:37statement value of this column for that
34:39row is going to be one same way the next
34:42time you enter something it'll be 2 3 4
34:45right and usually we use serial or big
34:49serial so there is another version which
34:51basically has more capacity the
34:55maximum number that you can store in big
34:57serial is a lot higher when it comes to
35:00serial so usually when you're dealing
35:03with production systems we go with big
35:05serial when we want to make ID as our
35:08primary key so primary key is basically
35:12a unique field using which we can
35:14identify a particular row in a table
35:16right now serial is an integer which is
35:19going to be automatically incrementing
35:22with each entry in our table then we
35:24have small int we have big int and we
35:27have integer all these three are
35:29basically integers just that the
35:31capacity as I said the maximum number
35:34that you can store an integer so this is
35:37how the scale works we have integer
35:40Which is less than small end Which is
35:43less than big end so depending on your
35:45need you can either go with integer
35:48small end or big end same way we have
35:51decimal and numeric which are mostly
35:53considered identical you can use either
35:56of them they pretty much much behave the
35:58same way right and the purpose of this
36:03is what does this 10 and this two means
36:06is it basically says you can store a
36:10number you can store a number in this
36:14format right on the right side of the
36:16decimal point there will always be two
36:19numbers right that's what this two means
36:22on the right side of the decimal point
36:24there will always be two numbers and
36:26what do 10 means is across all these
36:29numbers in this complete number across
36:33all these numbers in this numerical
36:34repes representation the maximum amount
36:37you can store is 10 so you can store
36:41something like 1 2 3 4 5 6 7 8 dot 9 0
36:48right now if you count it we have 10
36:51numbers we cannot store something like
36:54three here we cannot add something like
36:56this because the maximum we can store is
36:5910 numbers across this whole numerical
37:01representation right and on the right
37:04side we have two numbers this is what
37:07this means and the question mostly
37:10people ask is what is the difference
37:14between decimal or numeric something
37:17like this as compared to something like
37:19real or double Precision or float right
37:21now the difference is a little
37:23complicated floating Point numbers they
37:26can be real double float whatever you
37:28call them they are represented in a very
37:32different manner as compared to the
37:34decimal counterparts which we have in
37:36decimal and numeric so the thumb rule
37:40that you should have is if accuracy is
37:42an important aspect for that field so
37:47let's say you are storing an information
37:50like price for a field like price
37:52accuracy is very important right because
37:54it is going to be involved in a lot of
37:57calculation
37:58and a lot of things can go wrong if you
38:00have different different representations
38:03of the same number in different
38:04different systems etc etc right the
38:07accuracy is very important when it comes
38:08to a field like price so in this case
38:11you should always go with decimal right
38:14you should always stick with either
38:15decimal or numeric but standard says you
38:18can go with decimal right so if accuracy
38:21is an important aspect then always go
38:24with decimal because floating Point
38:26representation
38:28can have different different values
38:29across different different systems
38:31because of the way they are stored
38:33because of the way they are processed
38:36they have a very different algorithm
38:37when it comes to rendering or at the
38:40same time let's say you have a field
38:44like size right and it is a size of a
38:47area it can be something like five
38:5267.
38:538987 something like this right some
38:56fractional number some floating Point
38:58number where accuracy let's say if 89
39:0287 turns into 9 or 8 9 67 something like
39:09this very small discrepancies in the
39:13accuracy or the representation of the
39:14number does not impact a lot of
39:17difference in your systems when you have
39:20numbers like this you should go with
39:22floating points right now if you have a
39:25question like if decimals are always
39:28accurate then why shouldn't we always go
39:31with decimals and the reason is because
39:33decimals always have accurate
39:35representation of their value and
39:37because floating points don't have that
39:40kind of accuracy floating points are
39:42considered faster when it comes to
39:45storage when it comes to performing
39:47different different calculations etc etc
39:48right floating points are very fast that
39:52is the reason in a lot of scientific
39:54computation based domains roting points
39:58are preferred as compared to decimals or
40:01decimal
40:02representations so you should always
40:04evaluate what kind of value that you're
40:06going to store and if it is not
40:09something that is going to have a lot of
40:11impact if there are small discrepancies
40:13in the representation of the number then
40:16you should go with float because they
40:18are very fast to process and very
40:20preferable in these kinds of scenarios
40:23but if it is a value like price or
40:27something something very critical where
40:29accuracy matters a lot then always go
40:31with decimals right that covers pretty
40:34much all the floating Point data types
40:36then we have a very interesting category
40:38which are string categories and we have
40:42three types in that we have care V care
40:45and text now all these three data types
40:48store text that is the similarity
40:51between the three data types the
40:53difference is when we say car 10 and
40:56inside this field if he says store
40:59something like AB if you store something
41:02like this inside a data type which is
41:05declared as this and the length is
41:08defined as 10 then what the database
41:11system will do is it will pad extra
41:14eight spaces in that field before saving
41:17because we have defined the length is 10
41:21and it is a care data type right that is
41:25the property of character data type
41:27whatever length that you have defined
41:30does not matter the actual value that
41:34you're are trying to insert it will
41:36always try to store the same length if
41:39you don't provide the same length then
41:41it will just pad some empty spaces right
41:45inside whatever way it is represented it
41:47will add some empty spaces and it that's
41:50how it will store it and that is the
41:51reason people came up with another
41:53standard which is called Vare also known
41:55as variable character now the way it
41:57works is when we say the length is 255
42:01what it means 255 is the maximum length
42:05that you can store in this field but if
42:09you store something like this AB then
42:12the length will be two right it won't
42:14add Extra Spaces just to make a for this
42:16255 length if you store a smaller value
42:20then it will be two if you store
42:21something like a b c d then it'll be
42:25four etc etc right depending depending
42:27on what Valu are actually being inserted
42:30into the database it will adjust itself
42:33just that the maximum amount the maximum
42:38number that you can store is 255 you
42:41cannot exceed that if you do then you
42:42will get a database level error now the
42:46last thing is text which is a very
42:48modern alternative to Ware so imagine
42:52Vare without any length field basically
42:55any amount of text
42:57a text of any length that's what text
43:00means you don't enforce any length on
43:04this field you can store a text of any
43:07length usually it has some kind of upper
43:10limit like 250 MB or something something
43:13you can do your own research for that
43:16but yeah and when we say 250 MB of text
43:20it is very very very long text right
43:22usually we won't be needing that much
43:24but that's what it means now the
43:26question is when you want to store a
43:29string which one you should go with the
43:31first thing is never choose care right
43:34it it is a very old standard people used
43:37to do it way back so either go with
43:40varer or text you can use care if you
43:43know beforehand that the length is
43:47always going to be the same right it
43:49cannot be variable so let's say you are
43:53storing the codes of all the days of a
43:56week so the values can be M Mo or Tu or
44:01W Etc you get my point right if you have
44:05a requirement where you know that you
44:07have all these values and all of them
44:10have the same length then you can go
44:13with a data type like Car 2 and this way
44:17you won't be wasting a lot of space
44:20because of the variable length of
44:21different different entries of the data
44:24right only go with care if you have a
44:26use case like is but if it is a general
44:29text let's say name of a customer name
44:32of a product etc etc or a description
44:34Etc ET then either go with Vare or text
44:38now how do you choose Vare versus text
44:42what I believe personally is you should
44:43always go with text because if you go
44:48explore the documentation of Whois they
44:52themselves recommend that always use
44:54text which is the model alternative of
44:57Vare without length because most people
45:00what they confus with is if you use Vare
45:04with 255 this is going to perform better
45:08as compared to a field like text or you
45:11cannot index a field uh we'll cover
45:14index shortly but people believe you
45:16cannot index a field of type text there
45:19are a lot of misconceptions around this
45:21because other databases databases like
45:23MySQL SQL Server sqlite they have
45:26different different conventions the way
45:28they operate the way they function are
45:31very different from postgress and when
45:34people switch between different
45:35different databases they get confused or
45:38they are misguided so if you explore the
45:41official documentation of postgress they
45:44recommend that always go with text there
45:46is pretty much no performance difference
45:48between Vare or text and the second
45:51thing which is my personal opinion that
45:54using something like Vare 250
45:57which is by the way a convention from
46:00myql that people from myql which was a
46:04very popular database and that has a
46:07Convention of using Vare 255 and that's
46:11the reason a lot of people still use
46:12this and
46:14255 is at least when it comes to
46:17postgress 255 has a meaning in the
46:21context of a mySQL database but when it
46:23comes to postgress people just use the
46:26number 255 as a random number right it
46:30has no meaning whatsoever in a postgress
46:33database and people just use it without
46:36thinking just because the way it has
46:39always been done and that's why I
46:42personally believe instead of going with
46:43a random number like 255 go with text
46:47and and the reason is let's say later on
46:51you want to increase the length for some
46:53use case let's say you are dealing with
46:56a field called description and you just
46:58set the length is 255 as V so later on
47:03you want to increase the length so to
47:05cater to that requirement you have to do
47:07a database level migration which affects
47:11a lot of data and a lot riskier of
47:13course migrations are performed on a
47:15day-to-day basis but still you should
47:17always avoid a database level migration
47:19if you can right and that's the reason
47:22using something like text and enforcing
47:25the length for whatever it is on your
47:27application Level and since we are not
47:30in the data engineering domain we are
47:32not in the data analyst domain people in
47:35those domains they usually deal with SQL
47:39directly right they have some kind of
47:41interface and they write SQL directly
47:43and they see the result of the SQL data
47:46directly etc etc right SQL is their
47:48first point of interaction but as
47:50backend Engineers when we are dealing
47:52with backend systems we usually interact
47:55with SQL databases
47:57through a driver right we have different
48:01different drivers depending on what
48:02programming language that we are talking
48:04about and that's how we interact with
48:07the database through a driver and we
48:09have a lot of application code when we
48:12are dealing with the data that's the
48:14reason we can enforce the length or
48:17whatever constraint it is on the
48:20application code so that our database
48:23migrations all the database system
48:25database statements are simpler to read
48:28and simpler to maintain so let's say
48:30someone new someone new comes over and
48:33they look at this they see vat 255 and
48:37they think that this has some meaning
48:39even though the person who just created
48:43it they just added it without thinking
48:46right it is just a random number for
48:47them but if someone new comes over they
48:50will think there is some meaning to this
48:52number or there is some meaning to this
48:5410 number they will try to understand
48:56and where this is coming from and since
48:58there is no documentation they'll try to
49:00dig through the code Etc ET there's a
49:02lot of headache that comes with it
49:05because a number a number like this a
49:08number like this this represents that it
49:11has some kind of meaning even though it
49:13doesn't most of the times right so
49:17instead of this if you go with just text
49:20then it is a lot simpler to read a lot
49:23simpler to write these migration
49:25statements all the SQ statements because
49:27you won't have to think about these lens
49:30and all and if someone new comes over
49:32and they read it they just think that it
49:34is a text field it is a character field
49:35right there is no extra meaning to this
49:38so those are some of the concepts
49:40surrounding string Fields string data
49:42types in post moving on we have Boolean
49:46we can store true or false in this field
49:49we have date we can just store the date
49:52in this and we have time where we can
49:54store the time right in hour minute
49:57seconds format then we have time stamp
50:00for storing the information of date and
50:02time at the same time then we have time
50:05stamps with is extra Zed at the end
50:08which just means store the time zone
50:10information also in this so it will
50:12store time stamp and a time zone
50:16information then we have interval for
50:19storing like 10 days or one week etc etc
50:22right those kinds of datas then we have
50:24uu ID U ID is a very a popular choice
50:27when it comes to making table primary
50:30keys right because of their Ur flend and
50:33their unique nature so that's the reason
50:35posg offers a native uid type right
50:38inside the database then we have Json
50:40and Json b as I have mentioned before
50:43postgress offers native Json and we have
50:46an extra type which is called Json B
50:49also known as Json binary and the
50:51primary difference between Json and Json
50:53B is when we use a field called Json
50:57this will be stored as a plain text a
51:01plain text with the key value format
51:03that we usually see when we are reading
51:05Json but when we use this Json B this
51:11will be converted into a different
51:13format postgress will serialize it into
51:16its own native Json format for
51:19efficiency purpose so that it can
51:20perform better it can perform a lot of
51:22query capabilities etc etc right there
51:25something that is limited to postgress
51:28it is not an SQL standard and most of
51:31the times you should go with Json B
51:33because of the performance advantage
51:35that it offers then we have the aray
51:37types you can store an arrow of
51:39different different data types right
51:41store an arrow of integer you can store
51:42an AR of Json date time Etc whatever all
51:45the different different data types that
51:47we have then we have some other random
51:49data types like storing Network
51:52addresses Mac addresses and geometrical
51:54points XML etc etc that we don't really
51:58use on our data basis but if you do want
52:00to use it you can explore the official
52:02documentation and you'll find more
52:04information on that and this is how we
52:06insert data into our database we write
52:09insert into the table name and the Order
52:12of the all the fields that we want to
52:14insert the data in and then we provide
52:18all the values in the same order that we
52:21wrote Our fields in right and this is
52:23how we are inserting all the data this
52:25is an example example small integer this
52:28is an integer big integer as you can see
52:31it is a lot higher than a normal integer
52:34then we have decimal we have real double
52:37Precision which basically floating Point
52:39representations then we have character
52:42Vare and text and we have bullan we can
52:45either pass true or false here we have
52:47date we have time and hour minute
52:50seconds format we have time stamp where
52:53we have the date and the time we have
52:55time stamps you have date time and the
52:57time zone information then we have
52:59interval have uid this this is what a
53:01typical uid looks like we have Json Json
53:04B and while inserting even though Json
53:07and Json B looks the same but postgress
53:10serializes Json B into a different
53:12format for faster processing and faster
53:15retrial right then we have array then we
53:18have IP addresses Mac addresses
53:20geometrical points and XML etc etc right
53:23all the data types that we basically saw
53:25and that's pretty much all about about
53:26all the data types that we are going to
53:28deal with as backend engineers in a
53:31typical database system next up what we
53:33are going to do is we are going to
53:37design the database of a project
53:41management platform in the previous
53:44video we created the apis we designed we
53:48modeled the apis of a project management
53:51platform similarly to understand
53:54different concepts of databases and and
53:56different relevant Concepts not just
53:58theoretical concepts are very Advanced
54:00concept that we don't necessarily use on
54:02a day-to-day basis but very relevant
54:04Concepts in database systems especially
54:06in postgress we are going to design a
54:09database of a project management
54:11platform and we are also going to write
54:14queries for different different apis
54:16using the same databases now before we
54:19get into that just want to bring up one
54:22topic which are known as migrations in
54:26systems especially in production systems
54:29you don't necessarily just open a
54:33software like table plus and you just
54:36start writing queries right you cannot
54:39do that because if something goes wrong
54:42or even if something does not go wrong
54:44but there is no way to track what all
54:47changes that are applied to a particular
54:50databas over time or who applied it
54:53right there is no way to control the
54:56version or the control the state of the
54:59databases across different different
55:01times right and that is the reason most
55:03database systems follow something called
55:06as database migrations now database
55:09migrations are basically different
55:11different files let's say we have 1. SQL
55:15we have a folder which are called
55:17migrations inside the folder database
55:20right you have a folder structure like
55:22this you have DB folder inside that you
55:24have migrations and inside that you have
55:27different different files you have 1
55:29dsql you have 2. SQL you have 3 dsql etc
55:32etc right and in each file you have a
55:36couple of SQL statements normal SQL
55:38statements nothing fancy right you have
55:40create table or create index or drop
55:44table etc etc and with that you have a
55:47tool usually it's a command line tool we
55:49have a lot of command line tools for
55:53performing migrations and maintaining
55:54migrations for example Le we have dbate
55:58or we have go migrate right a lot of
56:01this famous tools now what this tool
56:04does it goes to this location DB
56:08migrations and goes through all these
56:11files in this sequential Manner and
56:14because of that we write the names of
56:17these files in a sequential manner
56:20either we perform some kind of numerical
56:22series 1 2 3 or we add dates uh
56:26timestamps and since time stamps follow
56:29a single uh flow that's the reason we
56:32get sequential files right okay now what
56:36this tool does it goes through all those
56:38files in that sequence and applies all
56:42the SQL statements basically executes
56:45all these SQL queries on that particular
56:47databases whatever database that you
56:49have configured in your environment it
56:52executes all this SQL statements on that
56:55data database inside migration also we
56:58have two kinds of migration we have up
57:00migrations and we have down migrations
57:03now some of the modern approaches of
57:05handling databases they don't really
57:07believe or they don't really Implement
57:09down migrations but this is the standard
57:12way of operating right you have up
57:13migrations up migrations are basically
57:16whatever change that you want to do you
57:17want to create a new table so you write
57:20create table etc etc you want to create
57:22a new type let's say you want to create
57:24a new enum type you write create type
57:27enom etc etc then you want to create
57:29some indexes whatever all the create
57:31statements you write one by one right
57:33with proper SQL syntax or postgress
57:37syntax then depending on the tool let's
57:40say a tool like dbate what it does it
57:44divides the same file the same SQL file
57:47let's say 1. SQL into two sections one
57:49section with a comment for up migrations
57:52and another section for down migrations
57:55now the purpose of down migration is
57:59whatever change you did in your up
58:01migrations whatever change you applied
58:03to the database in the down migration
58:06you have to revert all those changes so
58:09that the reason for having this feature
58:12called down migration is let's say you
58:14applied some migrations you applied some
58:16changes to your database systems and
58:19something goes wrong right or something
58:22breaks in your production system or
58:24anything can go wrong what what you want
58:26to do you want to roll back to previous
58:28version of the database without any
58:30changes right the state has to be the
58:32same for that to happen you have to have
58:35down migrations so that all the changes
58:38that you did in your up migration the
58:39down migrations can rever that so that
58:43you can go to a previous state you can
58:44roll back okay that's how a migration
58:49workflow works you have a tool and that
58:52tool usually creates a table called SK
58:56scha something like that in your
58:57database and using which it tracks that
59:00which is the current version of the
59:02database right let's say you have 1 SQL
59:062. SQL 3. SQL right then in your schema
59:10table you will have something like four
59:12right current schema is four because
59:14four is the latest changes that you have
59:17applied on your database when you come
59:18back and you want to add another file.
59:205. SQL before you apply that file before
59:23you up that migration your current data
59:26schema will still have four right that's
59:29how the tool works you have a migration
59:31tool which goes through all your SQL
59:33files applies all the SQL queries on
59:35your databases one by one if it is an up
59:37migration then it applies all the
59:39changes if it is a down migration it
59:41reverse all the changes for that version
59:43now the question is why do we need
59:44migrations there are a couple of reasons
59:46one reason as I've already mentioned you
59:48cannot just open a graphical tool and
59:50execute SQL statements because that's
59:52very hard to keep track of what are the
59:55all the changes that you made right
59:57unless you want to save it to a
59:59particular file and you want to commit
1:00:00to git etc etc and after all those
1:00:03things you will come up with your own
1:00:05migration system that's why we have this
1:00:07concept called migrations couple of
1:00:09advantages of using migration is one as
1:00:12I said keeping track of
1:00:15database changes keeping track of
1:00:18database changes over time right you
1:00:20have a file you have a lot of files in a
1:00:22particular folder which is committed to
1:00:25your version control system let's say
1:00:27it's git or git lab bit bucket whatever
1:00:30platform that you follow to Version
1:00:31Control your code usually your migration
1:00:33statements stay with your code and you
1:00:36commit it to get GitHub whatever
1:00:38platform you follow and over the time
1:00:41you keep adding new migration files to
1:00:43the same folder and that's how you keep
1:00:46track of all the changes that are
1:00:48happening to your database schema second
1:00:50is roll back as I already mentioned if
1:00:53something goes wrong you can roll back
1:00:55to a particular version so that's pretty
1:00:57much all there is to it migrations are a
1:00:59system using which you apply new changes
1:01:02on top of your databases you can add new
1:01:05tables you can modify tables you can
1:01:07create indexes you can create triggers
1:01:09etc etc right whatever change that you
1:01:13want to perform on a database you have
1:01:16to create a new migration for it because
1:01:19relational databases follow a particular
1:01:23strict schema you cannot just insert
1:01:26data randomly into the databases you
1:01:27have to follow a particular schema
1:01:30that's the reason we have this migration
1:01:31statements to make changes to the
1:01:33database over time using any command
1:01:36line tool now we will start modeling our
1:01:39database for our project management
1:01:41platform and for that we'll write
1:01:43migrations okay here I have my vs code
1:01:46open this is where we'll write all our
1:01:48SQL statements to model our database
1:01:52right so for the sake of migration we
1:01:54are going to use d mate it's a command
1:01:57line migration tool that helps applying
1:02:00all the changes to your database right
1:02:02and for that we have to provide the URL
1:02:05of our database to the tool and for that
1:02:08we have to create a new environment
1:02:10file. EnV and inside that we can create
1:02:13a variable called database URL and the
1:02:16tool will pick up the value of our
1:02:20postgress database URL from this
1:02:22location okay so to create our first
1:02:26migration dbate offers a command you can
1:02:29write dbate new create users St that
1:02:32sounds right so press enter it creates a
1:02:36new folder called DB inside that another
1:02:38folder called migrations and inside that
1:02:41a migration file so as I said it can
1:02:44follow a sequential number like 1 2 3 4
1:02:465 or time stamps whichever sequence that
1:02:49you want to prefer right in this case
1:02:52it's adding a time stamp then the name
1:02:54of our file which is created users table
1:02:57for now it's empty we'll add our
1:02:58migration statements here pretty soon so
1:03:01this is how as I mentioned this section
1:03:05is for writing out down migrations
1:03:07whatever SQL statements that we write
1:03:10after this comment are considered as
1:03:13down migrations and whatever SQL
1:03:16statements that we write before this
1:03:18down migration and after this up
1:03:20migration are considered as our up
1:03:22migrations right now to save some time
1:03:24I'll just paste all the SQL statements
1:03:26and then we can go through that one by
1:03:28one right I've pasted all the SQL
1:03:31queries that are needed to perform this
1:03:35migration the up migrations and create
1:03:37all the necessary tables so let's
1:03:40explore all the statements one by one to
1:03:43understand all the concepts surrounding
1:03:44it the first thing that you notice is we
1:03:48are
1:03:48creating some data types called as enums
1:03:53right now enums are basically all those
1:03:57values for which you have a predefined
1:04:01set of allowed values for example we
1:04:04have a field called status in the
1:04:07projects table and for that we only want
1:04:10to allow these three values the project
1:04:13status can either be active or completed
1:04:16or achieved active or completed or
1:04:19archived right in the same way for tasks
1:04:23in the task table the task status either
1:04:26can be pending in progress completed or
1:04:28cancelled same way for members they
1:04:31either can have the role owner admin or
1:04:34member the reason for using a data type
1:04:37called enum instead of just going with
1:04:40our standard text because first thing
1:04:44data Integrity data Integrity when we
1:04:47say in the context of databases we mean
1:04:50we leave the responsibility of checking
1:04:53the validity the checking the accuracy
1:04:55of the data
1:04:56to the database instead of our
1:04:58application code because we created
1:05:00types these enum types and we used these
1:05:04types let's say we created this type
1:05:07called project status and as you can see
1:05:09we used it here right in the status
1:05:11field that's the type of the status
1:05:13field is our custom inom type which is
1:05:16project status because we did this
1:05:19whenever we insert data or whenever we
1:05:22are trying to update data in the
1:05:24projects table and and in the field of
1:05:27status if we try to insert any random
1:05:30string or let's say we try to install we
1:05:35have active completed or archived we try
1:05:37to inster something something if we try
1:05:40to insert some random string like this
1:05:43we will get a database level error we
1:05:46don't have to check this in our
1:05:47application code we can leave that
1:05:49responsibility for the database we can
1:05:51check it in our application code that is
1:05:54just decreasing the scope of the error
1:05:56but still to make it more robust to make
1:05:59it more secure we can provide a set of
1:06:02allowed values and we can use that
1:06:04custom type for any field then whenever
1:06:08we insert some data whenever we update
1:06:10some data the database will check
1:06:13whether that data whatever value that we
1:06:16are providing for the Project's status
1:06:19whether it is one of these if it's not
1:06:22then we'll get a database level error
1:06:24okay the first thing is data Integrity
1:06:26the second thing is documentation and I
1:06:29think this part the second point is more
1:06:32important than the first point because
1:06:34the first point data Integrity this we
1:06:37can do in our application code right we
1:06:40since we are talking in the context of
1:06:42backends we have a programming language
1:06:44in our hand and we can validate whether
1:06:48whatever status that is coming from the
1:06:49user that is coming from the front end
1:06:51or whatever application code whether it
1:06:53is one of these strings or not completed
1:06:56or archived we can do that in our
1:06:58application code but another advantage
1:07:01of using enums in our migration
1:07:03statements is when you're going through
1:07:05your old migration statements for
1:07:07debugging something or let's say you are
1:07:09unboarding a new team member into your
1:07:11team and they are going through the
1:07:13database migration statements to
1:07:15understand what all changes that the
1:07:17project went through over the last
1:07:19couple of months or the last couple of
1:07:20years and they want to understand right
1:07:23what is the state of the database what
1:07:25are the past states of the database what
1:07:28changes happened over the time etc etc
1:07:31right and when they are doing that when
1:07:33they are going through all the database
1:07:35migration statements if they come across
1:07:37this table called projects and they see
1:07:40the field status and if it is of type
1:07:43text but in our application code we are
1:07:47only doing active completed archived now
1:07:50there is no way for them to find out
1:07:53this piece of information that you
1:07:55cannot put any arbitrary text into your
1:07:57status field it has to be either of
1:08:00these three right so to find out that
1:08:04piece of information they have to go
1:08:05through all the application code they
1:08:06have to see what what are all the places
1:08:09where this field is used and to track
1:08:11down all those use cases then they can
1:08:14boil it down to these three values which
1:08:17is a lot of headache right so using enum
1:08:22type provides some kind of documentation
1:08:24for you for your team members for your
1:08:26future team members so that at one
1:08:29glance you can tell what are all the
1:08:31allowed fields that can be in a
1:08:34particular field which makes everything
1:08:36very easy to understand right so that's
1:08:39all about enum fields we are creating
1:08:42three enum types and this is a syntax we
1:08:44write create type the name of the enum
1:08:48and we write as enum and inside the
1:08:50braces we provide all the allowed values
1:08:52we create three types three enum types
1:08:55and we are going to use this in our
1:08:57future tables now moving on we are
1:08:59creating a users table since it's a
1:09:02project management platform of course
1:09:03we'll have users right so that's the
1:09:06first table we are starting with we are
1:09:08creating a table called users and if you
1:09:11notice this each table has some default
1:09:14fields we have ID we have created it we
1:09:17have updated it same for user profiles
1:09:20you have ID created at updated at for
1:09:22projects we have ID created at updated
1:09:24so each table has this kind of metadata
1:09:27kind of field the ID is not really a
1:09:29metadata it is the primary key and by
1:09:32primary key I mean using this ID we can
1:09:36uniquely identify a particular Row in
1:09:39this table right let's say we want to
1:09:42find out or let's say in our backend API
1:09:45we have a requirement that we want the
1:09:47information of user okay since it's a uu
1:09:50ID let's generate a random uu ID and
1:09:53let's paste it and a comment here here
1:09:58okay now we have a requirement in our
1:10:01back end we have a API which takes the
1:10:04user ID in a dynamic parameter and we
1:10:07have to return the details of that user
1:10:10so this is the ID of that user and we
1:10:13have to find out the information of the
1:10:15user using this ID now if we don't make
1:10:19a particular field let's say the ID
1:10:21field primary key okay we don't assign
1:10:25the
1:10:26condition primary key to a particular
1:10:28field there's a couple of things that
1:10:30can happen this primary key property has
1:10:34some implicit properties those
1:10:36properties are if you write primary key
1:10:38for a particular field that field cannot
1:10:41be null not null and it also has a
1:10:44unique constraint so relational
1:10:46databases have this concept called
1:10:48constraints right you can apply a
1:10:50particular condition particular property
1:10:54to a field
1:10:56and that property or that condition will
1:11:00protect that field from going corrupt
1:11:02okay that's a very high level definition
1:11:04we'll see what that means when we
1:11:06encounter more examples so when we say
1:11:08primary key it means it implicitly has
1:11:11these two properties not null and unique
1:11:13though so this field cannot be null and
1:11:17this will always be unique if there is
1:11:19another entry with the same value gets
1:11:22inserted into this table we'll get a
1:11:23database level errors and because of
1:11:26this implicit properties and some other
1:11:28foreign key Behavior we use this
1:11:32property called primary key for our ID
1:11:34field so each table will have a field by
1:11:38convention called ID and we will assign
1:11:41the property primary Q to that which
1:11:44will help us fetch different different
1:11:46information of the user okay now what we
1:11:49are saying we have a field called ID it
1:11:52is of type uu ID and it will be a
1:11:55primary key for this table and by
1:11:59default if the ID is not provided when
1:12:02an insert statement is executed by
1:12:05default generate a random U ID okay this
1:12:08is what this means this is by default
1:12:10natively provided by postgress so if we
1:12:13don't provide the ID field which we
1:12:15generally don't we leave it to postgress
1:12:17the database system to generate a random
1:12:20ID for us and to assign it to that R
1:12:23next we have another field called email
1:12:26and it is of type text it is not null
1:12:29one thing to keep in mind is by default
1:12:32all the fields in a postgress table can
1:12:35have null values unless you explicitly
1:12:38specify that it cannot have null values
1:12:41More than 70% of your tables Fields
1:12:44should have the not null constraint
1:12:46right because this not null constraint
1:12:50enables the database to have a
1:12:51consistent state if you don't add this
1:12:55then the application can push null
1:12:57values into the table even though you
1:12:59don't do it uh intentionally because a
1:13:03lot of database interactions are also
1:13:06dealt with automated scripts so that
1:13:08script can have a bug and you'll end up
1:13:10with a lot of null values in your
1:13:12database which makes things very very
1:13:14difficult right so for a lot of reasons
1:13:17like that always try to stick to n Nal
1:13:21okay unless you have a reason for that
1:13:24field to be null okay that's the reason
1:13:28we are writing not null here we have a
1:13:30field called email it is of type text
1:13:32and it cannot be null and we have
1:13:35constraint called unique but this means
1:13:37is each door of this table will have a
1:13:40unique email the moment you try to push
1:13:43another row with the same email address
1:13:45that already exists in the table we will
1:13:47get a database level error that it
1:13:50violates the unique constraint okay and
1:13:53since email is something that we don't
1:13:56want to create two users with the same
1:13:58email we are applying this constraint
1:14:00called unique next we have a field
1:14:02called full name it is of type text
1:14:04again not null then we have password
1:14:06hash it is again of type text and not
1:14:09null since we don't directly store the
1:14:12plain text value of the password we hash
1:14:14the password and store it this it's
1:14:16called password hash just a name then we
1:14:19have two other fields create at and
1:14:21update at and the reason is we want want
1:14:25to know when this user was created okay
1:14:28when was the first time this user was
1:14:30created in our database that's the
1:14:31reason we maintain this field called
1:14:33created it and usually we don't manually
1:14:35insert it we are providing this default
1:14:40property and we are saying if created is
1:14:43not passed by default you can take the
1:14:46current time stamp and you can put it in
1:14:49that row okay and it is of type
1:14:52timestamp with time zone okay this is of
1:14:55type time stamp with time zone this will
1:14:58have the date the time and the time zone
1:15:00information same way updated it we
1:15:03create this field so that we can keep
1:15:04track of when was the last time we
1:15:07updated some field of this row okay and
1:15:11that can have some use cases for example
1:15:14if you have a table in your front end
1:15:16and you want to display all the users in
1:15:20the order of when was the last time
1:15:22their name was updated something like
1:15:24this right so in that case you can use
1:15:27this updated it property to sort by and
1:15:31that's all about users table some of the
1:15:33other things to notice here is all our
1:15:36tables have this plural form right we
1:15:39have users we have user profiles
1:15:41projects and that is a standard a lot of
1:15:43people also prefer the singular form
1:15:46user user profile project Etc ET it's a
1:15:50matter of what your team has decided and
1:15:53what your company has decided but the
1:15:56industry standard is to mostly stick
1:15:58with the plural form second thing all
1:16:02the table names and all the field names
1:16:04will be small case and snake case and by
1:16:08that I mean if it is a single word it
1:16:11will have small case of course as we
1:16:13have users ID email right all small case
1:16:17if it has multiple words let's say full
1:16:19name password hash created it update
1:16:22then we'll use snake case if you are
1:16:24coming from other progr programming
1:16:25languages or Etc you might have the
1:16:27instinct to go with uh camel case right
1:16:31you might want to write something like
1:16:32full name with n capital and you want to
1:16:36merge and get rid of the snake case but
1:16:37that is not a good idea because in
1:16:40postgress everything is case insensitive
1:16:43by Nature so even if you write camel
1:16:45case postgress will take it as so if you
1:16:49write something like this will name
1:16:52pogress will understand this will name
1:16:56unless you write it like this full name
1:16:59with quotes and when you're writing your
1:17:02application code using double Cod again
1:17:04and again can be very difficult and make
1:17:07the code very ugly that's the reason we
1:17:09always try to stick with small case we
1:17:12make everything small case and if you
1:17:14have multiple wordss we stick with snake
1:17:16case so that we can avoid using double
1:17:17codes to make postgress understand case
1:17:21sensitivity okay that's some of the
1:17:22things that you have to remember moving
1:17:24on
1:17:25we have another table called user
1:17:28profiles now if you check the commment
1:17:30it says one to one relationship with
1:17:33users now you might have a question like
1:17:36why are we creating a different table
1:17:38for storing information of the user
1:17:41right why don't we store all this
1:17:42information in the same table and the
1:17:45reason for that is you when you're
1:17:46designing a database you have to take
1:17:48into account some of the different
1:17:50different situations that you might
1:17:53modify your data in so if you think
1:17:56about a user the only times you are
1:17:59going to make changes to a users entry
1:18:04in the users table is when they are
1:18:06modifying their profile and their
1:18:09profile can have lot of other
1:18:10information for the sake of this example
1:18:12we have just limited it to their image
1:18:14URL their bio their phone number but
1:18:17user can have other fields also right
1:18:20they can have their social media
1:18:22accounts and they can have their
1:18:25websites and their projects etc etc a
1:18:29lot of different information a user
1:18:30profile can have and because of that we
1:18:32in the future we have to make a lot of
1:18:34migrations to the user table itself and
1:18:39we have to constantly modify the users
1:18:42row again and again and we don't
1:18:46necessarily have to do that if we
1:18:48abstract out the users profile
1:18:51information into a different table which
1:18:53can scale over time which can get bigger
1:18:55over time and which does not affect the
1:18:59primary users table directly these are
1:19:02some of the bu cases that we go with one
1:19:04to one relationship for storing users
1:19:07profile information for storing user
1:19:09preference for storing metadata etc etc
1:19:12right this is a common convention that
1:19:14you will see when it comes to modeling
1:19:16your database so we have a table called
1:19:20user profiles inside this we'll store
1:19:23the information of the user for this
1:19:25what we can do is we don't necessarily
1:19:27have to create another ID field because
1:19:29there is a one to one relationship with
1:19:31another table each entry of that table
1:19:35or each row of that table will only have
1:19:38one row in this table that's why it's
1:19:41called one to one relationship and
1:19:43because of that we can get rid of this
1:19:46ID and we can make the user ID which is
1:19:50the foreign key in this table as the
1:19:53primary key so we can write uu ID then
1:19:57instead of not null we can write primary
1:20:00key and we can also get rid of this
1:20:02unique thing now this user ID field is
1:20:06both the primary key and the foreign key
1:20:09in this table and we have some other
1:20:11fields for storing the image URL the bio
1:20:14the phone number and if you notice we
1:20:16are not writing notal here because these
1:20:18can be optional Fields a user can choose
1:20:21not to have a bio they can choose not to
1:20:24provide the phone number or to have a
1:20:26image customized image etc etc right
1:20:29that's the reason we are not writing not
1:20:31n in these fields okay moving on we then
1:20:35have another table called projects now
1:20:37the same thing happens here we have a
1:20:40primary key with ID and we are
1:20:42generating a default random ID each time
1:20:45we enter a new project into the database
1:20:48same way we have the name of the project
1:20:51which is not null and we have the
1:20:52description of the project which can be
1:20:54null we don't care much of the
1:20:56description but we have to have the name
1:20:58of the project that's why we are writing
1:21:01not null here same way we have a status
1:21:04field which is using our custom enum
1:21:07type is project status is not null and
1:21:11if you don't provide any value for this
1:21:13field by default it will be in the
1:21:15active State okay usually when we are
1:21:18going with enum types we provide a
1:21:20default value with one entries of that
1:21:23enum to make easier for us so that we
1:21:26don't have to explicitly push that value
1:21:28from our application code then we have
1:21:30an owner ID which is a foreign key and
1:21:33we write it like this it is a not n
1:21:36level field and says it references the
1:21:41users table and this is a constraint
1:21:44that on delete restrict and this is what
1:21:47it means this owner ID is the foreign
1:21:50key for stable and it references the
1:21:53user table and usually this is how we
1:21:56write users ID and because the ID field
1:21:59is the primary key in the users table we
1:22:02can omit this part and we can only say
1:22:06references users like we are doing here
1:22:08and it means owner ID references the ID
1:22:13field in the user table users table okay
1:22:17now the second part we are putting a
1:22:19condition here saying that on delete
1:22:21restrict this is also known as refer
1:22:24differential Integrity which basically
1:22:26means that we can protect the data
1:22:29across different tables using the
1:22:32relationship between those tables in
1:22:34this case what we are saying if someone
1:22:37deletes this particular user which user
1:22:41the user whose ID is in this table the
1:22:44project table as the owner ID so let's
1:22:47say we have a users table and we have
1:22:51projects table in ID field we have
1:22:55for the sake of this example let's say
1:22:57we have ID is one and in projects field
1:23:00we have another entry owner ID in this
1:23:03row owner ID is one so this user has
1:23:07created a project that's why in the
1:23:09projects table we have a row which has a
1:23:13field called owner ID and the value is
1:23:15one when we write on delete restrict
1:23:19what it means is if someone tries to
1:23:21delete this user this user whose ID is
1:23:25one the database system will check
1:23:27whether this user has some corresponding
1:23:30rows in projects field since it has what
1:23:34it will do is it will check what is the
1:23:36referential Integrity constraint what is
1:23:38the condition we are mentioning here
1:23:40since we are saying restrict it will
1:23:42fail that operation you cannot delete a
1:23:45user unless you delete the project first
1:23:49that's what it means using referential
1:23:51Integrity we can put some restrictions
1:23:54on some operations on some tables using
1:23:58the relationship between those tables
1:24:00and inside referential Integrity we have
1:24:03couple of constants one is on delete
1:24:06restrict second is on delete Cascade and
1:24:10what on delate Cascade means let's say
1:24:13if we had instead of on delate restrict
1:24:15we had on delate Cascade so when someone
1:24:18deletes a particular user the database
1:24:20system will check if there are entries
1:24:24in the projects table which has owner ID
1:24:26as one it will also delete those
1:24:28projects instead of restricting it will
1:24:30Cascade which means it will delete the
1:24:32user and all the associated projects
1:24:34from the projects table they also have
1:24:36another con condition called set null
1:24:39and set default which basically means if
1:24:42someone deletes a particular user then
1:24:45owner ID in case of set null will be set
1:24:49null but since we are saying not null
1:24:51here and if you try to set null then
1:24:53we'll get a database level error and
1:24:55this operation will not go through same
1:24:57way set default will try to set the
1:24:59default value if some default value is
1:25:02provided while creating the table these
1:25:04are pretty much all the referential
1:25:06Integrity constraints that we use on a
1:25:08day-to-day basis to protect our data
1:25:11from going corrupt to protect our data
1:25:14from going inaccurate right so this
1:25:16basically means we cannot delete a user
1:25:18as long as they have some Associated
1:25:21projects in the project table because of
1:25:24this statement on delete restrict and
1:25:26owner ID is a foreign key and similarly
1:25:28we have created it and updated it moving
1:25:30on we have tasks which another table and
1:25:35in the same way we have a primary key
1:25:37called ID and we have a foreign key here
1:25:40called project ID it is a type uu ID
1:25:44because the primary key of projects is
1:25:48ID and ID is of Type U ID and since
1:25:51we'll be storing the values of ID here
1:25:53this is is also U ID and we are saying
1:25:56not n which means there cannot exist a
1:26:00task without an Associated project ID
1:26:03that cannot be an orphan task that's
1:26:05what we are saying here it cannot be
1:26:06null then we have the foreign key
1:26:08constraint the referential Integrity
1:26:10thing you're saying it references
1:26:12projects and since we have AED the field
1:26:15it will check which is the primary key
1:26:18in Project table since ID is the primary
1:26:19key ID is the forign key here then we
1:26:22have the referential integrity
1:26:24constraint we are saying on delete
1:26:25Cascade now as I've already mentioned on
1:26:29delete Cascade means if we have a
1:26:31project with ID one and if we have a
1:26:36task with id2 and project ID 1 this is a
1:26:39projects row there is a task row and if
1:26:42we delete the projects row with ID one
1:26:45it will check that project one has
1:26:48Associated tasks in the task table so
1:26:51what it will do is since we are redit in
1:26:54on delete Cascade it will delete all the
1:26:57tasks which are associated with the
1:26:59project ID one because of referential
1:27:02Integrity this is a very useful Concept
1:27:04in relational databases then moving on
1:27:07we have the title field is of type text
1:27:09and not null and description which can
1:27:11be null and of type text then we have
1:27:15the priority which is an
1:27:17integer we can only store 1 2 3 4 etc
1:27:20etc and it cannot be null by default if
1:27:24we the application does not pass any
1:27:26values we are setting the value one then
1:27:29in the end we have a constraint of check
1:27:31in po or any relational systems we have
1:27:34different different constraints one we
1:27:37have already seen is unique so for that
1:27:40field in the whole table you can have
1:27:43only one value for a particular field
1:27:46and that value will be unique across the
1:27:48whole table then we have not null which
1:27:52enforces the condition that you cannot
1:27:54set null in this field similarly we have
1:27:57another constraint these are called
1:27:59constraints or conditions that we are
1:28:02putting on a particular field similarly
1:28:05we have check constant which basically
1:28:09using which we can put a particular
1:28:11condition on a field a custom condition
1:28:14and the operation the transaction will
1:28:17only go through as long as this
1:28:19condition is true that's what check
1:28:22means so if we see here you're saying
1:28:26when we are trying to insert the
1:28:27priority field if you do not pass
1:28:28anything set the default as one but if
1:28:31you do pass anything we are checking
1:28:33that the value should be either 1 to
1:28:36five that is the condition that we are
1:28:37putting here the value of priority
1:28:39should be 1 to 5 so that no one can
1:28:42insert some random value like 55 into
1:28:44the priority field we're only
1:28:46considering from value 1 to five moving
1:28:49on we have a field called status and
1:28:52this is a custom enum type and which we
1:28:54created at the start is of task status
1:28:58and it can have pending in progress
1:29:00completed cancelled so the status will
1:29:03have our custom type task status it
1:29:05cannot be null and by default the
1:29:07application if does not pass anything we
1:29:09are setting the value of pending here
1:29:11then we have a due date which is of type
1:29:13date we not considering time here or
1:29:15time zone we're just considering date
1:29:17here then we have assigned to we again
1:29:20have a foreign key condition so assign
1:29:22to is a foreign key which references
1:29:25users ID from the users table and the
1:29:29constraint the referential Integrity
1:29:30constraint that we are putting here is
1:29:33if the user of that ID is deleted and
1:29:36that users's ID is present in the
1:29:39assigned to field in the task table then
1:29:41for that row we are setting the value of
1:29:44assigned to as null that's what this
1:29:46means and similarly we have created it
1:29:48and updated it the nice thing about the
1:29:51foreign key constraint is because you
1:29:53have written that assigned to or in this
1:29:57case owner ID right since these are
1:30:00foreign keys and by default relational
1:30:02databases have this constraint called
1:30:04foreign key constraint because of that
1:30:06you cannot enter anything into the
1:30:09assigned to field if you try to enter
1:30:12some random string or some random uu ID
1:30:14it can be a valid uu ID but that U ID
1:30:18has to be present in the users table as
1:30:21a valid ID if that is not present then
1:30:24your insertion will fail okay that's
1:30:27what we mean by Foreign key constraint
1:30:29if you write references users this make
1:30:33sure that this U ID whatever uid that
1:30:35you are passing for this field this has
1:30:37a corresponding user entry in the users
1:30:40field another thing to notice here is
1:30:42this pattern is called one to many
1:30:45because we are writing project ID here
1:30:48which is a foreign key which references
1:30:50the ID field in the proess table which
1:30:52basically means that if we have a
1:30:54project with id1 that can have multiple
1:30:58tasks right multiple tasks in the task
1:31:01table which refers to this project using
1:31:05the field project ID in the task table
1:31:08right it can it will be one here and
1:31:11same way it will be one here it will be
1:31:13one here it will be one here right one
1:31:15project can have multiple tasks in the
1:31:18task table that's why it's called one to
1:31:20many relationship and this is how we
1:31:23implement it
1:31:24the first kind of relationship which is
1:31:26one to one relationship the way we
1:31:28Implement that is we take the primary
1:31:31key of the main table and we create
1:31:34another table and we make the primary
1:31:37key of the main table as the primary key
1:31:40of the second table also but instead of
1:31:42writing just ID we write the name of the
1:31:45table with ID so because we had the
1:31:48table called users for a one toone
1:31:51relationship with the user profiles
1:31:53table what we did we wrote ID and we
1:31:56used the users primary key from this
1:31:59table as a primary key in this table and
1:32:01instead of just writing ID we wrote it
1:32:03as user ID is the primary key in this
1:32:05table this is how we implemented one to
1:32:07one relationship and the way we
1:32:10Implement one to many relationship is we
1:32:12take the ID field and we create another
1:32:16table but we don't make that as a
1:32:18primary key we keep that as a foreign
1:32:19key only and we refer to that using the
1:32:24ID primary key right that's how we
1:32:27Implement one to many relationship in
1:32:29the next one we'll see how we Implement
1:32:31many to many relationship so moving on
1:32:34this is the last table it's called
1:32:36project members the reason we are
1:32:38creating this table is we want to keep
1:32:41track of what are all the projects that
1:32:43a user is part of at the same time we
1:32:46also want to keep keep track of what are
1:32:49all the users that are associated with
1:32:51the project so you can look at it both
1:32:55ways and when you have a condition like
1:32:57that when you have a condition when you
1:32:59take the same thing and you can look at
1:33:02it both ways and it makes sense that's
1:33:05how we know that it is a many to many
1:33:07relationship because if we have a user
1:33:10that user can be part of multiple
1:33:13projects at the same time right you can
1:33:14be part of multiple projects at the same
1:33:16time same way if we have a project that
1:33:19project can have multiple users at the
1:33:22same time right a project can not be
1:33:24limited to a single user same way user
1:33:26cannot be limited to a single project
1:33:28that's why projects and users have many
1:33:31to many relationship and we want to keep
1:33:34track of that relationship by creating a
1:33:37different table and usually we call this
1:33:40table as linking table and we implement
1:33:43this pattern when we are implementing
1:33:46many to many relationship okay by
1:33:49creating a different table for the sake
1:33:51of maintaining the relationship with
1:33:53between two tables that's why it's
1:33:55called a linking table and this is how
1:33:57we do it okay we have to make some
1:33:59changes to that instead of creating an
1:34:02ID here what we'll do we'll remove this
1:34:06we'll remove this row we'll take foreign
1:34:09keys from both the tables so what we'll
1:34:12do is we have project ID here and we
1:34:15have user ID here project ID is a
1:34:17reference to the ID field in the project
1:34:20table and we are seeing on delete
1:34:21Cascade as the referential integrity
1:34:23constraint same way user ID is a foreign
1:34:26key which references the users table and
1:34:29the referential Integrity constraint is
1:34:31the same thing on delete casket which
1:34:32basically means if the project is
1:34:34deleted delete all the entries in the
1:34:36project members table same way if the
1:34:38user is deleted delete on the ENT in the
1:34:40project members table okay and in the
1:34:43end what we'll do instead of writing
1:34:45unique we'll write primary key primary
1:34:48key and what this means is this is a
1:34:51composite primary key in the Technic
1:34:53terms so it is a combination of two
1:34:56fields which are foreign Keys
1:34:58referencing primary keys of two other
1:35:00tables and we take those two and we
1:35:03create the primary key so if a user is
1:35:07part of a project then that will have
1:35:10one entry in projects members table
1:35:13let's say you have users table and you
1:35:16have projects table okay and you have
1:35:21users 1 2 3 and projects 1 2 2 three and
1:35:25we want to maintain the relationship
1:35:26that let's say through some user Journey
1:35:30user one was added to project and we
1:35:33want to maintain this relationship in
1:35:34our projects members table what we can
1:35:37do we take project ID since it's a many
1:35:40to many relationship what we do we take
1:35:42the project ID which is two okay this is
1:35:46the project ID and you take the user ID
1:35:50which is one right take the user ID is
1:35:53one and this combined will have one
1:35:56entry in the project members
1:35:58relationship because user one being part
1:36:02of project two is a single event right
1:36:05that cannot be duplicated user one
1:36:07cannot be part of project two multiple
1:36:09times same way project 2 cannot have
1:36:12user one multiple times okay that's the
1:36:15reason what we did we took this
1:36:17combination project two and user one we
1:36:21took this we said that these two
1:36:24combined will be the primary key for
1:36:26this table because primary key
1:36:29implicitly enforces some constraints
1:36:32constraints like unique and not null so
1:36:36what we are saying this combination can
1:36:39only have one entry in this table which
1:36:42will be a unique entry and that cannot
1:36:44be null and because it is a primary key
1:36:47using this combination we can uniquely
1:36:49identify this Row in this table okay
1:36:52this is the CR of how we Implement many
1:36:55to many relationship in postgress or any
1:36:58relational database using a linking
1:37:00table which will have a composite
1:37:03primary key of the two tables that we
1:37:05are trying to link the rest of the
1:37:07things remain same we have created it
1:37:09and updated that and we have a role
1:37:10field which is again a custom enum so we
1:37:14are saying it is a member role which we
1:37:16have created if we go to the top you're
1:37:18saying member role it can be either
1:37:20owner admin or member Okay so
1:37:24if a user is part of a project in that
1:37:27project whatever characteristics that
1:37:29user will have or whatever project
1:37:32characteristics for that user it will
1:37:34have all those informations we can store
1:37:37in the project member St and because
1:37:40role is specific to the situation where
1:37:43a user is part of a project that's why
1:37:45we have we have kept the information of
1:37:47role in this table okay and by default
1:37:51we are setting the role member and that
1:37:53that's pretty much all our up migrations
1:37:57same way as I mentioned we have to
1:37:59mention our down migrations all the
1:38:01changes that we did we created a couple
1:38:03of types we created a couple of tables
1:38:06now in the down migrations what you have
1:38:08to do we have to revert that so that
1:38:10when we want to roll down to a
1:38:12particular version using these
1:38:13statements our database can do the roll
1:38:16back okay we have to explicitly say that
1:38:19these are the down migrations that the
1:38:21database tool the migration tool can use
1:38:25to roll back to a previous version okay
1:38:28and we are simply dropping all the
1:38:30tables and after dropping all the tables
1:38:32we are dropping all the types in the
1:38:34reverse order that we created them
1:38:35that's pretty much all the tables okay
1:38:38so let's go ahead and apply these
1:38:41migrations to our database so that we
1:38:43can see if it works or not and to apply
1:38:46it dbat has a command you can write DB M
1:38:49and you can write up okay and here
1:38:52applying this migration file and it says
1:38:54applied in this
1:38:56milliseconds and then we go here if we
1:38:59do a refresh and you can see you expand
1:39:02it a little bit these are all the tables
1:39:05that we just created you can go here and
1:39:07you can check the schema it has project
1:39:09ID user ID role C project all the
1:39:12schemas right since we have not inserted
1:39:14any databases yet all these entries are
1:39:17empty all these tables are empty and you
1:39:20can also see there is a special table
1:39:22called schema migrations and this one is
1:39:25created by dbit as I've already
1:39:28mentioned all these migrations tools
1:39:31they have to keep track of what is the
1:39:33current state of the database so that
1:39:36they can decide what migrations to apply
1:39:40right so after this after our first
1:39:42migration if you create a different file
1:39:45the database tool will check what is the
1:39:47current version and it will start
1:39:49applying the migrations from that point
1:39:51on instead of duplicating the Mig s and
1:39:55because if it tries to execute the same
1:39:57statements again it will get an error
1:39:59from postgress that this table already
1:40:01exists you cannot run the same
1:40:02statements again that's the reason the
1:40:06migration tool maintains a table call
1:40:09schema migration and in that it has a
1:40:13single field called version and it keeps
1:40:15tag of what is the current version of
1:40:17the migration that we have now that we
1:40:19have our tables ready we want to insert
1:40:22some data into it now in production
1:40:24environments when you actually deploy
1:40:26this back end you will have normal user
1:40:29flows right people will come to your
1:40:31platform they'll use the front end to
1:40:34sign up with forms and they'll create
1:40:36projects with different different forms
1:40:37you have this pre defined flows when the
1:40:41data will come into your database but
1:40:44when you're creating your backend when
1:40:46you're modeling your data for a backend
1:40:48engineer when you want to test all those
1:40:51changes then you want to see how the
1:40:54user interactions will look like
1:40:56basically for testing purposes in
1:40:58development environments you want to put
1:41:00some test data into your database so
1:41:03that you have something to test with
1:41:05before you deploy whatever changes that
1:41:08you made in the database for that
1:41:10purpose we have a concept called as
1:41:13seeding and seeding basically means you
1:41:16write some script usually you create
1:41:19another migration or you can put it in
1:41:22the same migration also but the best
1:41:23practices say you create different
1:41:26migration file for seeding data seing
1:41:29test data test data into your database
1:41:32and it's called sitting basically seting
1:41:34means putting some test data into your
1:41:36database for testing purposes in
1:41:38development environments so let's create
1:41:41another migration file with the command
1:41:44dbate new seat data SE data and when you
1:41:49press enter it creates another file
1:41:51called the time stamp stamp and the seat
1:41:54data because this time stamp is greater
1:41:55than the previous one these will be
1:41:58sequentially arranged and now this is
1:42:00end empty what I'll do is I'll again
1:42:03paste some SQL statements to save some
1:42:06time then we can go through what's
1:42:07happening there how we are inserting the
1:42:09data for seeding purposes these are all
1:42:12the SQL queries using which we are
1:42:15putting some test data into our database
1:42:17into our tables so there is nothing
1:42:19special here basic SQL queries if you
1:42:22have already explored the basics of SQL
1:42:24the basics of postgress they'll you
1:42:26understand it if you not then please do
1:42:28it it'll make understanding this video
1:42:30much easier so what we doing we are
1:42:33using a CT also called as common table
1:42:35expression to make it more readable so
1:42:37we are creating an intermediate table
1:42:40called inserted users and in that we are
1:42:43inserting some test data into the users
1:42:46table taking some sample emails some
1:42:48names some password hashes and we're
1:42:51inserting it and we returning two fields
1:42:54for this SQL query execution the IDS and
1:42:57the emails of the inserted users and we
1:43:00are taking that and this is an
1:43:02intermediate tib called inserted
1:43:05profiles what we are doing here is we're
1:43:07taking the inserted users table and
1:43:11using this from inserted users we are
1:43:14doing select select the ID of the user
1:43:18and we putting the image since the
1:43:21Avatar URL you have mentioned here we
1:43:23are putting some static image URL and
1:43:26for the bio we are doing a case wi so if
1:43:29email is something like this then put
1:43:31this bio if email is something like this
1:43:33then put this bio for this put this bio
1:43:36otherwise put some logic to put
1:43:39different different bios for different
1:43:41different users then for the phone field
1:43:44we are just inserting some random phone
1:43:47number then moving on same way we are
1:43:51inserting some project
1:43:53and etc etc using SQL queries just
1:43:57normal CD so let's go ahead and apply
1:44:01these migrations on our database so that
1:44:03we have some data to test with for
1:44:06applying the migrations we can do dmate
1:44:08up and we do it it applies seeds all the
1:44:12data into our database and we can go to
1:44:15our tool and we can open any table so as
1:44:19you can see projects has some entries
1:44:22you can
1:44:23click on a row projects project members
1:44:27users all the tables have some some
1:44:29entries and you can check the entries of
1:44:31the table for users we have this ID this
1:44:35email this full name password hash for
1:44:37the second user we have these entries
1:44:40when you go to user profiles we have
1:44:42this user ID after URL bio for the
1:44:45second user this is the BIOS third user
1:44:48this is the bio etc etc like same way we
1:44:50also have projects right so our CD is
1:44:53successful and we have some data so that
1:44:57we can start testing now now let's say
1:45:01we have created the tables we have done
1:45:04some seeding and now we want to build
1:45:08some apis for the first API that you
1:45:10want to build is you want to fetch the
1:45:13list of all users and you want to send
1:45:15it to the front end for that we can
1:45:17write a simple query and do select from
1:45:20users and we can execute this and we'll
1:45:23get all the entries right the all the
1:45:26users that exist in the users table now
1:45:29what you want to do is for each user we
1:45:32also want to send the profile
1:45:34information which is on a different
1:45:36table right we have the user profiles
1:45:39table so for each user we want to fetch
1:45:42the profile information from the user
1:45:44profiles table and you want to embed
1:45:46that into the user row and you want to
1:45:50send it to the front end in a single API
1:45:52call we use we don't want the user to
1:45:55make a different call for fetching the
1:45:57profile information that's why we are
1:45:58embedding the profile information before
1:46:01we send it so let's write the query for
1:46:03that usually when we write SQL queries
1:46:06always start from from section right
1:46:08instead of the select section so that
1:46:10you know exactly where you are drawing
1:46:12your data from so we write from
1:46:16users you and this is called an Alas and
1:46:21assigning an alas usually a one letter
1:46:24or two letter alas to a particular table
1:46:26name inside an SQL query makes it more
1:46:29convenient to refer to that table again
1:46:32and again in that query right that's why
1:46:34we use Al SS now from users table we
1:46:37want the information of the user next
1:46:40thing what we want is we want user's
1:46:43profile information which is in a
1:46:45different table okay and it is in the
1:46:49user profiles table now the thing that
1:46:53connects these two tables as you already
1:46:55know is the foreign key so each user
1:46:58profile entry each row in the user
1:47:00profiles table has a field called user
1:47:04ID which is a foreign key which refers
1:47:07to the primary key of the user table so
1:47:09what we can do we can use the join
1:47:12operation to join the users table with
1:47:15the user profiles table on a condition
1:47:17which is the user ID should be the same
1:47:20okay and to write that we can say left
1:47:23join and the reason we are using left
1:47:26join is because for some reason if the
1:47:29user profile in the user profiles table
1:47:32there is not an entry for a particular
1:47:35user okay it is possible in our in our
1:47:38backend system it is possible that the
1:47:40user has never edited their user profile
1:47:43that's why we have never created an
1:47:44entry for them in the user profiles
1:47:46table so in these situations if we go
1:47:50with inner join we will get an mty
1:47:53result because what inner join does each
1:47:55condition for a particular condition
1:47:57there should be an entry for both the
1:47:59tables okay since in this case we want
1:48:03the user information in any case right
1:48:06in any case does not matter whether they
1:48:08have the profile information in the user
1:48:10profiles table or not but we want the
1:48:12user information anyway that's the
1:48:15reason we are going with left joint so
1:48:17that even if there isn't an entry in the
1:48:19user profiles table we'll still get the
1:48:22value of the users information from the
1:48:24users table okay that's the logic behind
1:48:27going with left joint and most of the
1:48:29times we'll be using inner joints and
1:48:32left joints then we are writing SQ
1:48:34queries those are the mostly used joints
1:48:36you want to join with the user profiles
1:48:39table and we'll name it alas up and the
1:48:43condition for the joining is on the join
1:48:47condition is u. ID the ID field in the
1:48:50users table should be the same as the
1:48:54user ID field in the user profile table
1:48:57this is the condition okay this is the
1:48:59condition on which we are joining both
1:49:01these tables now we know where we are
1:49:04drawing our data from okay we have
1:49:05joined two tables we have an join table
1:49:08and now what we can do we can select in
1:49:11the select phase we'll see what are the
1:49:13data that we want to fetch now that we
1:49:16know where we are drawing our data from
1:49:18we'll see what data we are drawing from
1:49:20what we'll do we want to fetch
1:49:23everything from the user R so we'll say
1:49:26U do star comma we want to add another
1:49:30field in each row called profile okay so
1:49:35for that field what you want you want
1:49:38the corresponding Row from the user
1:49:40profiles table and you want to convert
1:49:44it into a Json and we want to embed it
1:49:47into a field in the user row called as
1:49:50profile okay for that what we can do we
1:49:54write 2 Json B which basically converts
1:49:58a particular row into a Json it is a
1:50:01inbu function provided by pogress and we
1:50:04can use that to convert it and we can
1:50:06write take up. STAR which means take the
1:50:10corresponding Row from the user profiles
1:50:12table convert it into a Json and name it
1:50:15as profile before returning okay we have
1:50:18our query now now let's try running it
1:50:21okay and when we run it let's see what
1:50:25the data looks like and this is what the
1:50:28data looks like we have all the fields
1:50:30from the users table we have ID email
1:50:32full name password hash created at
1:50:34updated that and we have an extra field
1:50:37called profile which is a Json and that
1:50:40has all the information from the user
1:50:42profiles table okay now using this query
1:50:45in a single API we can send the users
1:50:49data and the user profile data from a
1:50:51single database call okay using joints
1:50:54another thing to notice here is whatever
1:50:56data whenever we run a particular query
1:50:59in any relational data the data that we
1:51:03get returned is in a random format they
1:51:05don't follow any particular format so
1:51:08because of that whenever we run a select
1:51:11query whenever we are returning a list
1:51:14of data points into our front end we
1:51:16have to sort it by default using some
1:51:19column and usually what we do we sort it
1:51:22by the
1:51:23created it column because we want to
1:51:25return the data in the reverse order of
1:51:28when they were created so that the user
1:51:30can see all the latest users so for that
1:51:33what you can write order by U do created
1:51:36at you want to take the created at field
1:51:39from the users table and we want to sort
1:51:41by that and we want to sort by
1:51:43descending because we want the latest
1:51:45entries and when you do that and run it
1:51:49we get all the users in the reverse
1:51:51order of how or when they were created
1:51:55okay and this is what the query for an
1:51:59API of get all users looks like so if we
1:52:03have an AP something like this
1:52:06slv1 SL users if we have an endpoint
1:52:11which is a get endpoint our backend can
1:52:14use a query like this a database query
1:52:17like this to return all the data to the
1:52:19user of course there will be other
1:52:21processing that will happen this the
1:52:22serialization Der serialization
1:52:23depending on what language that you are
1:52:25using if you're using something like
1:52:27JavaScript or typescript or nodejs then
1:52:30the serialization overhead is not that
1:52:32much but if you're using something like
1:52:33go then it has to deserialize into its
1:52:36own struct then that struct will be sent
1:52:40by serializing into a Json format before
1:52:43it gets sent over the Internet to our
1:52:46front end right this is what a typical
1:52:49get all users endpoint looks like now
1:52:51let's see another end point which is
1:52:53something like slv1 SL users SL a
1:52:58particular user ID okay so we'll write
1:53:01it as user ID we'll get it as a dynamic
1:53:04parameter in our API and we can pass
1:53:07that user ID to our database query as a
1:53:10parameterized query we'll see what
1:53:12parameterized query means but if you
1:53:14don't understand this part please was
1:53:16the previous video where we have done a
1:53:19deep dive on API designing and what are
1:53:21Dynamic parameters how we design these
1:53:23API end points etc etc so let's jump on
1:53:26what this query will look like catching
1:53:29the information the profile information
1:53:31and the user information of a particular
1:53:33user given a user ID from our Dynamic
1:53:36parameter before we get into that let
1:53:41understand what is a
1:53:45parameterized queries parameterized
1:53:47query is basically a safety mechanism
1:53:51provided by databases which basically
1:53:53means before running a query you can
1:53:57provide a particular slot can provide a
1:54:00particular slot and you tell the
1:54:03database that this is your query and at
1:54:07this position there is an empty slot but
1:54:11before I execute this query I will
1:54:13provide the information in this slot now
1:54:16the catch is whatever information I
1:54:18provide here it will be a string you can
1:54:22cannot pass it you cannot pass it to
1:54:26render it as a database action call
1:54:30right it will just be a string so if
1:54:33someone passes something very dangerous
1:54:36like so we have a query and inside the
1:54:40slot if you pass like let's say delete
1:54:42from users a query which deletes
1:54:44everything deletes all the users in the
1:54:46database that will not be considered as
1:54:49a SQL query because the way
1:54:52parameterized query works is whatever
1:54:54you pass in this slot they are
1:54:56considered as a string okay they are
1:54:59escaped in the technical term and it is
1:55:01a safety mechanism to avoid situations
1:55:05avoid vulnerabilities like SQL injection
1:55:08where if you are constructing your query
1:55:12instead of using parameters you are
1:55:14constructing by concatenating Different
1:55:16Different Strings you constructing your
1:55:18SQL query instead of using parameters
1:55:21then you can be a victim to SQL
1:55:24injection okay so this is a very
1:55:26important concept you can do your own
1:55:28research to understand how SQ injection
1:55:31Works etc etc but to simplify everything
1:55:34whenever you have a dynamic value in
1:55:36this case we want to fetch the
1:55:39information of a single user using the
1:55:41ID of that user so the ID of the user is
1:55:44the dynamic value here so what we want
1:55:47to do we want to keep a particular slot
1:55:50in our query and we tell the database
1:55:53that when we run this query we are going
1:55:55to provide the ID of the user but for
1:55:57now it is just an empty slot and when we
1:56:00provide the ID it will it should just be
1:56:02considered as an user's ID just a simple
1:56:04string nothing else no more power should
1:56:07be given to this particular string okay
1:56:11that's the use of parameterized query it
1:56:14makes your query more secure to execute
1:56:17and most of the times whatever database
1:56:19driver whatever library that you are
1:56:21using whether in nodejs or go rust
1:56:24python whatever it is your database
1:56:27driver your OM they have capabilities to
1:56:31handle all these slots with parameters
1:56:33and etc etc since we are not getting
1:56:36into code or any specific programming
1:56:38language here we'll be looking at how
1:56:41parameters work in the SQL editor itself
1:56:45fortunately the this table plus the
1:56:48software that we are using to write our
1:56:51queries and to see our results etc etc
1:56:54they are providing an interface to
1:56:56provide parameters to our query so we
1:56:58can see how it works but in real world
1:57:02when you're actually building backend
1:57:04you'll handle parameters using your
1:57:06library using your driver whatever
1:57:08driver that you are using okay with that
1:57:11let's write our query to get the
1:57:13information of a single user for that we
1:57:16don't really need to change much we
1:57:18still want all the information of the
1:57:19user from the users table we still want
1:57:21all the information of the user from the
1:57:22profiles table using this Json
1:57:25conversion the only thing that will
1:57:26change is we want to filter by users's
1:57:29ID when a single users information now
1:57:32for that we want to add a where clause
1:57:34and write where users ID u. ID is equals
1:57:39to a parameter so this is where we are
1:57:41assigning a slot an empty slot we are
1:57:44telling that this is the name of the
1:57:46variable is called user ID and this is
1:57:50the whole query and we are saying that
1:57:52this is the query and this is an empty
1:57:54slot and when we run this query we'll
1:57:57provide you the value of this slot so
1:57:59that you can do your comparison and show
1:58:01us the results so let's run this and we
1:58:06are shown this dialogue so that we can
1:58:09pass the actual value of the user ID but
1:58:12as I said in your actual backend
1:58:15environment you'll be handling this in
1:58:17code in your particular driver or
1:58:19Library so for this let's let wrap this
1:58:23we have to wrap it in single codes right
1:58:27all the strings in SQL have to be
1:58:31wrapped in single code to be interpreted
1:58:34as strings that's why we are wrapping it
1:58:36in string and we are pasting The UU ID
1:58:39of the user okay this is the U ID I have
1:58:42pasted it here and then let's run this
1:58:46and when we run this we get the
1:58:48information of a single user and you can
1:58:50check this is the user ID we still
1:58:53getting all the information from the
1:58:54users table and we're still getting all
1:58:56the information from the profile table
1:58:58but in this case we are only getting the
1:59:01information of a single user using our
1:59:05parameters with the same query so this
1:59:08if you remember was for the endpoint V1
1:59:12SL users SL colon user ID so ideally
1:59:20while routing when the front makes the
1:59:22API call with the appropriate U ID value
1:59:27this will be routed to your particular
1:59:28Handler the Handler will pass it to your
1:59:30service the service will pass it to a
1:59:31repository and it will pass the user ID
1:59:33the actual U ID you'll take the U ID and
1:59:36you pass it in the appropriate parameter
1:59:39using the slot thing that I mentioned
1:59:41and after you get this result you'll get
1:59:45the result like this and this will get
1:59:47serialized and transferred over to the
1:59:49friend end in Json format going back to
1:59:52the get all users API the get all users
1:59:55query what if we want to provide some
1:59:58Dynamic filters or some Dynamic sorts
2:00:01usually in apis like these where we
2:00:05fetch an array of entities like get all
2:00:08users get all projects get all task in
2:00:11the same API we also have to support
2:00:13some kind of dynamic sorting or some
2:00:15kind of dynamic filtering or both at the
2:00:18same time now the problem is without you
2:00:22using these queries without constructing
2:00:24these queries in a proper orm or using a
2:00:28programming language constructing the
2:00:30SQL query
2:00:32ourselves showing that part of the
2:00:35mechanism in a SQL editor is a little
2:00:38difficult but we can imagine how the
2:00:41query might get constructed in an actual
2:00:44programming language when we are
2:00:46actually writing our backend code and we
2:00:49can focus on just the SQL query part
2:00:52without focusing too much on how we are
2:00:53going to construct the query so if you
2:00:56want to go back to the earlier query
2:00:58which was get all users so when we
2:01:01remove the Weare clause and when we run
2:01:05this we're getting all the list of all
2:01:07the users just as we had before now we
2:01:11want to add some Dynamic sorts and some
2:01:13Dynamic filters now let's see what all
2:01:16fields we have in the users table we
2:01:18have ID email full name password hash
2:01:21let's say we want to add a filter
2:01:24condition and we want to filter by the
2:01:26name and our condition will be we will
2:01:29pass a first letter of the name and we
2:01:32want to return all those users who have
2:01:36the first letter add that particular
2:01:38letter whatever the front end is passing
2:01:40that is going to be our filter condition
2:01:44and for sort we want to take the sort
2:01:46order from the user and we want to take
2:01:48this field by which the user wants to
2:01:52sort the result okay and as I said it's
2:01:55a little difficult showing how the quer
2:01:57is going to be constructed because what
2:02:00happens in an actual backend is let's
2:02:02say this is our query this is our query
2:02:04payload and it's say p generated query
2:02:08right so user can send these all query
2:02:11parameters they can send a page query
2:02:14parameter if they don't send it by
2:02:16default we are going to set pages one
2:02:19same way they are going to send a limit
2:02:23parameter if they don't send it we set
2:02:25it as something like 10 or 20 whatever
2:02:28makes sense in your use case then we
2:02:31come to the filtering part so as I said
2:02:35for the filter we want to filter by the
2:02:38first letter of the name so let's say we
2:02:42take a query parameter called letter and
2:02:46if they don't pass it then in this case
2:02:49we don't set any default if they don't
2:02:50pass it then we set it as null or in an
2:02:55actual backend system we don't include
2:02:57this in our query itself okay when they
2:03:00constructing our query dynamically we
2:03:02check that if the user has passed this
2:03:05query parameter or not if they have pass
2:03:08we include it in the we Clause if they
2:03:10have not then we don't include it at all
2:03:13okay that's how we do it in an actual
2:03:15backing system same way we check the
2:03:20sort conditions now the first thing is
2:03:23we want to check let's say sort by you
2:03:26check if this query parameter is present
2:03:29or not if this is present then we
2:03:31consider that as a sorting parameter
2:03:34usually we don't allow the user to pass
2:03:36any field as sort parameters uh we give
2:03:40them some options that you can either
2:03:43pass let's say full name or by email or
2:03:48by created ad okay we give them some
2:03:52options some fields from the table that
2:03:55we allow user to pass and depending on
2:03:58that we give them the result and the
2:04:01last thing that we allow them is sort
2:04:04order what is the order that you want
2:04:05your results in whether it is ascending
2:04:08order or descending order now for these
2:04:11two Fields what we do we check if the
2:04:13user has passed a sord by parameter then
2:04:17we need consider that for the Sorting
2:04:19mechanism if they have not by default we
2:04:22take creat at as the default sorting
2:04:25parameter same way we check if they have
2:04:28passed sort order or not if they have we
2:04:31consider whether it is ascending or
2:04:32descending if they have not by default
2:04:34we take descending so if the user has
2:04:37not passed any of this what do we end up
2:04:40with we end up with these query
2:04:42parameters by default we set the pages
2:04:45one limit as 10 sld by created at and
2:04:51order by descending right by default we
2:04:54anyway give them results as per this but
2:04:57we also give them the option to
2:04:59customize how they want the results
2:05:02right now with that let's see how we can
2:05:04construct the query we have our filter
2:05:07which we are considering as the first
2:05:09letter of the name we have our sort and
2:05:12we allow them to sort by email or full
2:05:14name or create at and we also uh want to
2:05:19pigate this since it is a list of all
2:05:22users whenever we are creating list apis
2:05:25we should most of the time try to pigate
2:05:28it unless we have a particular reason we
2:05:31have a particular user interface where
2:05:33we don't want to Pigeon it but most of
2:05:36the time we should pigeon it okay now
2:05:39going back to our query we have this
2:05:41normal query now what we want to do we
2:05:44want to add some more capabilities to
2:05:47this so the first thing is we want to
2:05:49add the filter condition you want to
2:05:52give users the ability to filter by the
2:05:56first letter of the name of the user so
2:05:59what we can do we say where U do full
2:06:03name I like I like means the SQL
2:06:06operator like but it is case insensitive
2:06:10so it does not matter is upper case or
2:06:13lower case it will still try to match
2:06:15the pattern okay I like and inside this
2:06:19what we do we pass a parameterized query
2:06:22and the parameterized query will be say
2:06:24letter okay then we concatenate with
2:06:28let's say the percentage sign let's run
2:06:31this query and let's provide the letter
2:06:36G and let's run this and we are getting
2:06:39two results because these two users have
2:06:42the first letter of the name starting
2:06:45with J that's why we're getting these
2:06:47two results now let's try to run this
2:06:49with another letter let's say x for this
2:06:53we don't get any results because we
2:06:54don't have any users who have names
2:06:57starting with x same way if we try to
2:07:00run it with something like a we get the
2:07:03user Alice Brown right so the filter
2:07:06part is working as expected and for
2:07:10those uh who are not familiar with the
2:07:12basics of SQL what this we are doing is
2:07:15we are taking the parameterized query
2:07:17whatever is coming from the front end
2:07:19and we are concat erating that with this
2:07:23symbol this percentage symbol what this
2:07:25means is take the letter whatever the
2:07:29first letter is so if we pass J this is
2:07:31what happens J and the percentage symbol
2:07:35and this goes to the I like pattern
2:07:39matching so what we're saying give us
2:07:41all the names which is starting with the
2:07:44letter j but we don't care whatever
2:07:47comes after that okay that's the reason
2:07:49we are getting all the users who have
2:07:51the first letter with J okay now we have
2:07:54our filter condition implemented let's
2:07:57go ahead and Implement our sort
2:07:59conditions so as you can see we are
2:08:02adding the default sort condition
2:08:04created at descending here now what we
2:08:07want to do we want to make it Dynamic so
2:08:11we want to say order by this is a
2:08:13parameterized query we want to say Do by
2:08:16and as order we also want to make it a
2:08:20parameter they're saying sort order okay
2:08:23we have our sort conditions let's check
2:08:25this and we have three parameters to
2:08:27fill now so let's provide it as J and
2:08:31for the sort by in the back end we have
2:08:33to construct this parameter in a way
2:08:36that it matches the existing query since
2:08:38we are using Al SS in our existing query
2:08:41we have to provide the sort condition in
2:08:45the same way what we want to do we want
2:08:47to sort by the emails of the user so so
2:08:51the parameter we should pass is U do
2:08:55email right because we have to match the
2:08:57alas that is existing in this query same
2:09:00way sort order we want to say descending
2:09:04and let's run this and we are getting
2:09:06two results John do and Jan Smith and
2:09:10this is how it is sorted John comes
2:09:13first then comes Jan so let's try to run
2:09:17this again but this time make it
2:09:18ascending now Jane comes first and John
2:09:21gum second so our sort conditions are
2:09:24also working as expected now the last
2:09:27thing we also want to pigate this query
2:09:31since it is a list of all users we want
2:09:33to pigate this query now in the end we
2:09:35can write the user is trying to fetch
2:09:38page one we have page and limit for the
2:09:41concept of page if you want to fetch the
2:09:44first page in the query we have to add
2:09:47something like offset it and we want to
2:09:50take also a parameter for here so we
2:09:52write page page range you want page now
2:09:55the second thing is we also want to take
2:09:57the limit and for the limit we also take
2:10:01a limit parameter and now let's run this
2:10:04we have two more parameters for now we
2:10:06want page as zero now in the actual back
2:10:10end the user will pass pages from one to
2:10:15whatever the maximum amount and we are
2:10:18setting also the page number is one but
2:10:20since we we are talking about the actual
2:10:22database query here we have to pass the
2:10:25first page as zero right the offset
2:10:27starts from zero that's how we want to
2:10:30differentiate between the actual
2:10:31database query and whatever is set for
2:10:34the experience of the user the we want
2:10:37to start from the offset zero then the
2:10:39limit is one since we are only getting
2:10:41two results for this query we want to
2:10:43check if the pation is working as
2:10:45expected or not that's why we are
2:10:46setting the limit is one and when we are
2:10:48run this we getting Jan myth as the
2:10:51first result and when we try to run this
2:10:54again but this time we wanton page the
2:10:56second page in the backend concept it is
2:10:59the page two and in the database concept
2:11:01it is offset one and when we run this we
2:11:04getting job okay so the page ination
2:11:06concept is also working and as I
2:11:09mentioned these things will change a
2:11:13fair amount when you are actually
2:11:15writing the EXL query in your back end
2:11:17because you have to construct all these
2:11:19queries dynamically you using your
2:11:21programming language but to understand
2:11:24what happens at the database level this
2:11:26example is pretty much enough so far we
2:11:29have seen what the database query looks
2:11:32like for this API get all users and this
2:11:36API get a single user now let's proceed
2:11:39to creating a user which is post / aa/
2:11:44users let's see what the query for this
2:11:46will look like now if you're already
2:11:48familiar with SQL basics this is a
2:11:51simple insert operation what we want to
2:11:54do is want to do an insert call insert
2:11:58into users you want to insert into users
2:12:02table and what are the columns that we
2:12:04are passing we are passing email and
2:12:07full name and the password hash which
2:12:10we'll create in our backend code but for
2:12:13the sake of this example we are just
2:12:14passing the password hash second we want
2:12:17to pass the actual values and let's use
2:12:20parameterized queries here for
2:12:22email then for name and then for
2:12:28password and this this camel case
2:12:31password hash and in the end we want to
2:12:35return what all users that were created
2:12:39using this query for that we can do
2:12:42returning Stu so return all the users
2:12:45all the rows that were created using
2:12:47this query so let's try to run this we
2:12:49have to pass all the parameters and in
2:12:52single codes since these are all strings
2:12:54right so for email we can do something
2:12:56like test at
2:13:01gmail.com and for the full name we can
2:13:04do test test and for the password any
2:13:08random stream right for the sake of this
2:13:11example then let's run this and we run
2:13:15it we are getting a single row as a
2:13:17result because we are doing returning
2:13:19star and we just created one user we are
2:13:22getting a single user entry a new user
2:13:24was created and we're getting all the
2:13:26information for that user and when we go
2:13:28to the users table we can see that a new
2:13:31user with test at gmail.com is created
2:13:33and is in the table okay okay and this
2:13:38is corresponding to the post / API SL
2:13:42users API since we are creating a user
2:13:45so we did a insert operation and created
2:13:48a user and return the response in this
2:13:50API next now let's get to update a user
2:13:56now going back let's go to our query
2:13:58editor minimize this now as I mentioned
2:14:02before in our actual backend code we
2:14:05will be constructing these SQL queries
2:14:07dynamically depending on what are the
2:14:10parameters that is passed from the user
2:14:14okay so for the for the update API what
2:14:18the API usually looks like is it is a
2:14:20patch API
2:14:21and we are giving the user to update
2:14:24certain properties of their profile okay
2:14:28we are trying to update the user
2:14:30profiles table and we are giving the
2:14:33user a form some kind of form in the UI
2:14:35to update their profile so they can
2:14:38update their bio they can update their
2:14:39phone number or they can update their
2:14:42image URL in the field Avatar URL for
2:14:45this we want to make the payload partial
2:14:47and by that I mean they can pass either
2:14:52all the three fields or they can pass a
2:14:54single field but depending on what are
2:14:56the fields they are passing we only have
2:14:59to update that field for all the other
2:15:01fields we don't touch that okay so in
2:15:05the programming language depending on
2:15:07what you're using we check what are the
2:15:10fields that the user has passed and from
2:15:13a set of allowed Fields so let's say we
2:15:15check if bio is present then take the
2:15:18latest entry what the user has passed
2:15:21the latest value of bio and update that
2:15:22in the database same way we check if the
2:15:24phone number is passed update it but
2:15:28Avatar URL is not passed then don't
2:15:30touch it keep it the same okay so with
2:15:34that understanding going back to our SQL
2:15:37query editor what query we can write is
2:15:39after going through our backend code we
2:15:41have seen that the user has only passed
2:15:43bio and phone number so this is what the
2:15:47query is going to look like after
2:15:49getting constructed okay we say update
2:15:53user
2:15:54profiles then set bio equals to this is
2:15:58going to a
2:15:59parameterized query bio equals to bio
2:16:03comma they have also passed phone number
2:16:06and phone equals to phone we're going to
2:16:10pass these values in our parameterized
2:16:12queries and we also have to pass for
2:16:15which user we want to update uh usually
2:16:17we'll take this as a dynamic parameter
2:16:19from the URL as as you can see here
2:16:22we're taking the ID of the user from the
2:16:24URL so that's what we will pass in our
2:16:26database right and we want to update the
2:16:30information the profile information of a
2:16:33single user right so we have to pass
2:16:36that in our parameterized query for that
2:16:39we can write where user ID which is a
2:16:41field in the user profiles table equals
2:16:44to a parameter called user ID and in the
2:16:48end we are saying whatever row that you
2:16:49have updated return the latest value of
2:16:52that row and then let's run this and for
2:16:55Bio we are seeing updated bio for phone
2:16:57number we passing a new phone number and
2:17:00we run this and when you check it you
2:17:03can see the bio is updated and the phone
2:17:05number is also updated this particular
2:17:07user and that's how an update user API
2:17:09will look like now I want to show
2:17:13something else if you notice here we
2:17:16have a field called updated at and the
2:17:20purpose of keeping this field in a table
2:17:23is every time a particular row is
2:17:25updated we also have to update this
2:17:28field corresponding to that row to the
2:17:31current time stamp the time stamp when
2:17:34the row was updated and if we check the
2:17:37field this is same as the created it
2:17:39this is the same as when the user was
2:17:42first created it is not updated since we
2:17:45just updated the value uh right now this
2:17:49should have the current time stamp which
2:17:51it is not now usually there are two ways
2:17:53of achieving this first is the manual
2:17:56way every time you are doing an update
2:17:59operation you can explicitly set the
2:18:03value of updated column to the current
2:18:05time Stam using your application code
2:18:07you can pass another parameterized query
2:18:09and you can say updated at equals to
2:18:12updated at okay you can do that or you
2:18:16can use another feature of databases
2:18:19called trigger
2:18:21and what triggers do is you can set a
2:18:23particular condition and when that
2:18:27condition is met you can perform some
2:18:29action that's the whole idea of using
2:18:32triggers at database levels so what we
2:18:35are trying to do here is we will set up
2:18:38a workflow using which what will say is
2:18:42every time we are updating a particular
2:18:45Row in any table we want to set the
2:18:49updated at field of that row to the
2:18:52latest time stamp using triggers okay we
2:18:55want to make that change so that we
2:18:57don't have to manually change the
2:18:59updated at field every time we update
2:19:02the information of a particular user
2:19:04okay for that we have to write another
2:19:06migration that is one change that we
2:19:09want to make the second thing that you
2:19:12should know about which is very
2:19:14important concept is indexes or indices
2:19:18what is database indexes is right this
2:19:21is a very important concept and it
2:19:23affects the performance of your queries
2:19:26a lot okay so we have to understand what
2:19:28is indexing and we have to implement it
2:19:30in our own database using a migration
2:19:33now let's understand what indexing is in
2:19:35the first place so going back to our
2:19:38earlier query so if we go to the history
2:19:40tab here and let's check what was
2:19:45earlier query so let's say this one okay
2:19:50and let me close this and on this this
2:19:54one right there is a select query for
2:19:58for the list of all users okay and if
2:20:01you notice here we are using some
2:20:04conditions here let's try to find out
2:20:06what are conditions that we are using
2:20:08the first thing that you notice is we
2:20:10are joining with another table and here
2:20:14we are saying the ID of the users table
2:20:17should be same as the user ID in the
2:20:21user profiles table this is the join
2:20:24condition here and it is an equality
2:20:26condition okay same way another thing
2:20:30that we are doing here is we are sorting
2:20:33by the email field in the users table
2:20:36and we are sorting in the order of
2:20:37ascending this second thing to notice
2:20:39and I'll explain why we are drawing
2:20:41attention to this part right now these
2:20:44are the two things now coming back to
2:20:47what are database indexes index is
2:20:51basically means by the normal definition
2:20:54if you are familiar with the index
2:20:56section of a book so we Google it let's
2:21:00say book index this is a typical index
2:21:05section of any book and what we see here
2:21:09is the writer of the book or whoever the
2:21:12publisher is they have created an index
2:21:14section where we they are saying you can
2:21:17find chapter one starting from page it
2:21:20and and chapter 2 starting from page 29
2:21:22chapter 3 starting from page
2:21:2435 etc etc right all the chapters are
2:21:28given here and the corresponding page
2:21:30number where you will find the starting
2:21:32of that chapter and because of this
2:21:34index section if someone wants to
2:21:37directly skip to chapter 4 they don't
2:21:41have to open the book and they don't
2:21:43have to go Page by page page by Page
2:21:45let's say the book has around so it says
2:21:4782 let's say the book has around 100
2:21:50pages
2:21:51so to find the chapter
2:21:534 the user does not have to go through
2:21:5650 pages one by one in order to reach
2:21:59chapter 4 just to find the location of
2:22:03the chapter 4 they don't have to
2:22:05manually scheme through 50 pages just
2:22:07for the sake of finding the location of
2:22:09a certain page right they can directly
2:22:12refer to the index they can see that
2:22:15chapter 4 starts from page 54 and they
2:22:18can directly jump to page 54
2:22:21right in the same way when we are
2:22:23talking about
2:22:24databases going back to our earlier
2:22:27tables this is the task table we have a
2:22:30bunch of tasks and every task has a
2:22:32single ID right and we can see all the
2:22:36results in this particular format
2:22:38because it is a software which fetches
2:22:40all the rows from our database and shows
2:22:42us in a sequential manner but when the
2:22:45database stores our data it is not in a
2:22:48sequential manner right every entry in a
2:22:51row might be somewhere else since in the
2:22:54earlier part of this video we have
2:22:55discussed that the databases that we are
2:22:58talking about relational or non
2:23:00relational these are disk based
2:23:02databases which means the database takes
2:23:05our data and stores it somewhere in the
2:23:08disk somewhere right it can be anywhere
2:23:10in a very efficient format it follows a
2:23:12lot of algorithms a lot of complex
2:23:14systems goes behind where to store which
2:23:17data etc etc but on a very high level on
2:23:20a very simple way of understanding we
2:23:23can assume that each row is stored
2:23:25somewhere in the disk right if we have a
2:23:29query where we want to find out the
2:23:32information of this particular task with
2:23:34this particular ID which we can pass in
2:23:37a parameterized query and you want to
2:23:40fet the information of this particular
2:23:41task what is the Brute Force without
2:23:43thinking about indexes what is the Brute
2:23:45Force way the database system has a
2:23:48bunch of tasks and it has has stored all
2:23:51the task in different different
2:23:52locations right in in a physical hard
2:23:55disk when it gets a query which says
2:23:57that we want the information of this
2:23:59particular task what it has to do it has
2:24:02to go through all the task one by one to
2:24:05find out if the ID matches this if the
2:24:07ID matches this if the ID matches this
2:24:09etc etc and finally when it reaches this
2:24:13ID okay it it has a match it can see
2:24:17that the ID that we have passed it
2:24:20accurately matches this particular ID
2:24:23and then what it does it Returns the
2:24:26information of this particular ID to us
2:24:29and we have our result now what happened
2:24:32is we sent a query the database did a
2:24:35sequential scan okay it went through all
2:24:39the tasks one by one in different
2:24:41different locations of the disk as I
2:24:43said the database system has a very
2:24:46complex way of storing the data in
2:24:48database right and it when it went to
2:24:51all those locations and it checked
2:24:53whether the ID matches this item whether
2:24:55the ID matches this item etc etc and
2:24:58until at the end it found a match and it
2:25:01returned the information which as you
2:25:03can already see is a very tedious and a
2:25:06very time-taking and a very inefficient
2:25:08solution okay now since we only have
2:25:12around six entries in this table it
2:25:15might not seem a lot uh it is a lot fast
2:25:18but imagine if we had add a, entries or
2:25:21a million entries or a billion entries
2:25:23in the table then going through all
2:25:26those items one by one and checking from
2:25:29different different locations of the
2:25:31disk can take a lot of time and can make
2:25:34the query very inefficient so for that
2:25:38purpose what the database offers is a
2:25:42feature called index what index does in
2:25:45the same way a book index gives us all
2:25:48the page numbers for a particular
2:25:51chapter if you want chapter 4 we can
2:25:53directly see that it starts from page 28
2:25:56same way on a very high level not to go
2:25:59into the technical Deep dive of how
2:26:01indexes work how B tree Works etc etc
2:26:04which you can do your own research for
2:26:06but just for understanding the Practical
2:26:08purpose of index why we use indexes for
2:26:12each ID so we'll understand how index is
2:26:14actually implemented practically but for
2:26:17each ID so we can index a particular
2:26:21field of a particular table let's say if
2:26:24we index by ID so what an index contains
2:26:27is for each ID you have the location
2:26:30here okay for each ID like this okay for
2:26:33each ID from here for each ID it has an
2:26:36table for each ID it has the
2:26:39corresponding
2:26:40location of the row right where exactly
2:26:44in the disk in the hard disk the
2:26:47information of this particular task is
2:26:49stored
2:26:51so it has another table a lookup table
2:26:54where it stores the ID of the task and
2:26:56the location of the task same the ID of
2:26:58the second task location of the second
2:27:00task etc etc now that it has an index
2:27:03like this when it gets a query which
2:27:05says that we want the information of
2:27:08this particular task what it does
2:27:10instead of looking through all the items
2:27:13all the tasks in the disk from different
2:27:15different locations one by one what it
2:27:16does it refers to the index it tries to
2:27:19check whether this exists in the index
2:27:22or not so as you can see the index is a
2:27:25direct access it is not stored in
2:27:27different different parts of the disk it
2:27:29is stored at one place in sequentially
2:27:32so it does it is very fast to go through
2:27:34all the entries so it checks whether it
2:27:37matches the first one the second one the
2:27:39third one the fourth one the fifth one
2:27:40and it finally finds that this entry so
2:27:44it is somewhere here this one matches it
2:27:47so it directly finds this entry in a
2:27:49very short time and in the corresponding
2:27:52lookup value it finds the location where
2:27:55exactly the information for this task is
2:27:57stored in the hard disk and it gets the
2:27:59location goes to that location directly
2:28:01and returns whatever value is stored in
2:28:03that location directly to our user
2:28:05whoever made the database query in the
2:28:08first place now as you can see compared
2:28:10to the previous operation which was a
2:28:12sequential lookup going through
2:28:14different different locations across the
2:28:16hard disk and trying to find out whether
2:28:18the ID that we have passed matches the
2:28:21current ID or not etc etc and finally
2:28:24return the result as compared to this
2:28:26approach where we have a lookup table
2:28:28where we are storing the ID of each item
2:28:31and the location of that item okay and
2:28:33we are directly giving the result of
2:28:36that to the user and that is the purpose
2:28:39of index index is basically a lookup
2:28:43table you can imagine it as a lookup
2:28:46table which has information for a
2:28:48particular field and the location of the
2:28:51particular Row for that field now that
2:28:54is the first property of the index it
2:28:56has a lookup table and it can directly
2:28:58access whatever value that you have
2:29:00passed from this table and it can find
2:29:02the corresponding location of the entry
2:29:04it can return you the result the second
2:29:06property of the index is the order of
2:29:08the index it can be either ascending it
2:29:11can be descending so if you remember in
2:29:14the previous query where we are saying
2:29:16we want to return the list of all users
2:29:18sorted by descending order right now for
2:29:22that query to perform as efficiently as
2:29:26possible because we have a requirement
2:29:28like that what we can do first thing is
2:29:31we want to create an index on created at
2:29:34right we want to take the field instead
2:29:36of ID we are taking the index created at
2:29:39and we want to index that field so that
2:29:41when we execute that query the database
2:29:44can instantly find all the created at
2:29:47fields and the corresponding Row for the
2:29:50that created at field and it can return
2:29:52it the second thing is because the sort
2:29:55order is also in the picture we also
2:29:58have to decide in what order we want to
2:30:01index either ascending or descending or
2:30:04both of them okay we can create
2:30:06different different indices but it all
2:30:08depends on our requirement so as you can
2:30:11see by default we are returning the
2:30:13descending order of creat De so when
2:30:16creating the index we can say that we
2:30:19want to create an index on the field
2:30:21created at in the descending order so
2:30:24that when we execute that query which
2:30:27has order by created at and descending
2:30:31the index can quickly go through all the
2:30:34created at field that is already ordered
2:30:36in descending order and it can quickly
2:30:39return that result instead of if it had
2:30:42all the creat FI in ascending order then
2:30:44it will have to go through all of that
2:30:46and you have to rearrange and do a sort
2:30:48and then return right depend depending
2:30:50on our requirement we can customize the
2:30:52behavior of the indices okay that's a
2:30:55very high level introduction to indices
2:30:57so what you have to remember is every
2:30:59time you are using a wear clause or a
2:31:01join condition and depending on what is
2:31:03the frequency that you are doing that
2:31:05but is the frequency that you're doing
2:31:07the join condition or the we Clause you
2:31:09can decide to create an index on that
2:31:12condition so that the subsequent queries
2:31:14are faster because how the database does
2:31:17the lookup so the two two things that we
2:31:21saw one thing is we have to create
2:31:23trigger so that the updated at field is
2:31:25automatically updated every time we
2:31:28update a particular row of the user
2:31:30second is we have to create indexes so
2:31:32that the join conditions and the wear
2:31:34Clauses and the Sorting conditions are
2:31:37faster okay so let's go ahead and create
2:31:39a migration which covers all these I
2:31:41have gone ahead and created a new
2:31:43migration file using dbate and pasted
2:31:46all the uh index create statements and
2:31:48the trigger statement so let's go
2:31:50through and understand what's Happening
2:31:52Here what are we exactly doing here so
2:31:55in the first section you can see in the
2:31:57up migrations we are creating a bunch of
2:31:59indices the first one we are creating an
2:32:02index on the email field in the users
2:32:05table because we have let's imagine we
2:32:08have an API where we have to find a
2:32:10particular user by the email or we have
2:32:14a database query we where we are joining
2:32:18the users table with the task table
2:32:21depending on the email of the user right
2:32:24in the join condition we have the
2:32:27condition where we are matching the
2:32:28email because we have a requirement like
2:32:31that we decided that we want to index
2:32:33the email field of the users table so
2:32:36that in join conditions and in the wear
2:32:38Clause we can quickly find the
2:32:40corresponding user given a particular
2:32:43email using the index and that was the
2:32:45reasoning behind using email or index
2:32:49ing email from the users table so this
2:32:52is the syntax looks like this is a
2:32:54generic SQL syntax same way we are
2:32:57creating an index on the created field
2:33:00for the users table in descending order
2:33:03because if you remember the select query
2:33:06the get all users API where we are by
2:33:10default returning all the users sorted
2:33:13by the created field in descending order
2:33:16since we have an API like that and it is
2:33:19pretty free frequently called that's the
2:33:21reason we want to optimize the query
2:33:24execution of that particular database
2:33:26query by creating an index on the
2:33:29created at field in the descending order
2:33:31so that the database can do a fetch
2:33:34operation very fast as compared to FH
2:33:37operation without using indices okay
2:33:40same way for the task table we are
2:33:43creating an index on the project ID so
2:33:46if you remember going back to our first
2:33:49migration where we created the table we
2:33:52have the task table and we have project
2:33:55ID here okay and this is a foreign key
2:33:58so imagine we have an API where we are
2:34:01fetching all the tasks of a particular
2:34:05project right and for that APA we have
2:34:08to create a database query where we have
2:34:11to take the projects table and we have
2:34:14to join it we have to left join it with
2:34:17the task table depending on the it ID
2:34:19field of the project table and the
2:34:21project ID field in the task table that
2:34:24is going to be our join condition right
2:34:26these two has to match now as I said
2:34:29that whatever field is involved in your
2:34:32join conditions or in your wear Clause
2:34:34if you index that field that operation
2:34:37is going to be much faster now by
2:34:39default whatever field is the primary
2:34:42key of the table that is by default
2:34:45automatically indexed by your database
2:34:48right you don't have to manually do it
2:34:50so in the join condition two fields are
2:34:51involved the ID field and the project ID
2:34:54field from Project table and the task
2:34:56table so since ID field is the primary
2:34:59key in the projects table we don't have
2:35:01to think about this this is
2:35:02automatically indexed by the database
2:35:05but in the task table we have the field
2:35:08project ID is is a foreign key and this
2:35:11is involved in the join condition and
2:35:13since it is involved in the join
2:35:15condition we want to index it because it
2:35:17is not index by default since it is a
2:35:19foreign key it is not the primary key in
2:35:21this table so that is the reasoning
2:35:23behind indexing in this migration we are
2:35:27creating an index on the project ID
2:35:29field on the task table because we have
2:35:32a join condition where we want to fetch
2:35:35all the task of a particular project
2:35:37right for that we have to make a left
2:35:39join in the left join we we have a
2:35:41condition where we are matching by the
2:35:43project ID and that's the reason we want
2:35:46to make that operation little faster
2:35:48that's why we are indexing by project ID
2:35:50field in the task table same way in the
2:35:53task table we have an assigned to okay
2:35:57this is also a foreign key so imagine
2:35:59another API where we want to fetch all
2:36:04the task of a particular user so this
2:36:06assigned to is a foreign key which
2:36:08references the users table so this will
2:36:12have a corresponding entry in the user
2:36:13table with ID of that user right so to
2:36:16implement that a what we have to do we
2:36:19have to take
2:36:20the users table and we have to join it
2:36:23with the task table on the condition
2:36:25that assign to has to match users. ID
2:36:29right since ID is the primary key of the
2:36:31users table we don't have to think about
2:36:33that but in this table assign two is a
2:36:36foreign key right so we have to Index
2:36:40this field to make the join operation of
2:36:43joining users table with task table a
2:36:45little faster that's why we are creating
2:36:49an index on the assigned to field in the
2:36:51task table okay next we are creating an
2:36:55index on the created at field in
2:36:57descending order in the task field
2:37:00because the same reasoning if you want
2:37:03to return the list of all tasks to show
2:37:05it on our front end by default the API
2:37:08returns all the tasks sorted by the
2:37:11created at field in descending order
2:37:13because we want to return all the latest
2:37:15tasks and we can fetch all the latest
2:37:18task by sorting all the tasks in
2:37:20descending order and to fetch all the
2:37:23tasks in descending order to make that
2:37:25operation a little faster we are
2:37:27creating an index on the created it
2:37:30field in the task table in descending
2:37:31order right same way we are creating an
2:37:34index on the status field because in the
2:37:36get all tasks API let's say we have a
2:37:39filter condition in the filter condition
2:37:41what we are doing we want to fetch all
2:37:43tasks so if we go to task status we are
2:37:46creating an custom ENT type and we have
2:37:48four types of status pending in progress
2:37:51completed and cancelled now let's
2:37:52imagine in the get all tasks API we want
2:37:55to fetch all tasks which have the status
2:37:58pending okay we have a requirement like
2:38:00that and the front end the user can pass
2:38:04any Dynamic status right the pending
2:38:06progress completed whatever right and we
2:38:10want to quickly fetch all the tasks
2:38:12depending on what is the status of the
2:38:14task and because the status field was
2:38:17involved in a wear Clause what is the
2:38:19condition for creating an index or what
2:38:21is the thumb rule if that field is
2:38:23involved in join condition or in a wear
2:38:26clause or in a sort condition okay these
2:38:29three are your primary guidance on when
2:38:33you should consider creating an index
2:38:35for that field okay since status field
2:38:38is used in a Weare Clause we can
2:38:42consider creating index on the status
2:38:44field in the task table now another
2:38:46thing is you should not create an index
2:38:48right away whenever you have a condition
2:38:51that field is used in a we clause or a
2:38:53join condition or a s by you have to see
2:38:57and you have to evaluate how frequently
2:38:59that query is being called or if the
2:39:03performance trade-off is worth it or not
2:39:05since to maintain an index the database
2:39:09at all times has to take that field
2:39:11let's say you have the project ID field
2:39:13in the task table project ID and in the
2:39:17lookup we have all the locations of the
2:39:19task right we have all these entries to
2:39:22maintain this index to have the latest
2:39:25state of all the tasks in that index
2:39:28what the database has to do every time
2:39:30you do an insert task or every time you
2:39:33do an update task this index has to be
2:39:37accurately maintained and to maintain
2:39:39that every time you do an insert or
2:39:41update the database has to do some kind
2:39:44of operation to store the latest state
2:39:47of the task in the index
2:39:49table right and which adds some kind of
2:39:53overhead some kind of overhead even
2:39:56though it is not a lot and it depends
2:39:58what is the size of your database how
2:40:00many entries you have in your database
2:40:02index operations them CS can add some
2:40:07kind of overhead so as a backend
2:40:10engineer you have to evaluate these
2:40:11conditions that whether creating an
2:40:14index is worth it or not whether the
2:40:17overhead of maintaining an index IND is
2:40:19worth it or not and that depends on how
2:40:22frequently your database query is
2:40:23executed and what kind of user
2:40:26experience that you want to provide at a
2:40:28tri you have to consider a lot of
2:40:30parameters but on a very high level
2:40:32without thinking about all this micro
2:40:35optimizations you can take these three
2:40:37parameters that whether that field is
2:40:38involved in a join condition or a wear
2:40:40clause or a sort operation if it is and
2:40:44you see that that query is frequently
2:40:46called then you can go ahead and create
2:40:48an index on that
2:40:49and if you in the future you see that
2:40:51that query is not being frequently
2:40:53called then you can just go ahead and
2:40:55delete that Index right okay but as a
2:40:57start you can consider creating it and
2:41:00monitoring your performance etc etc same
2:41:02way we are creating an index for project
2:41:05I in Project members we are creating an
2:41:07index on user ID in Project members etc
2:41:09etc right the same logic the same kind
2:41:11of reasoning applies everywhere okay
2:41:13that's pretty much all about index now
2:41:15coming to the triggers part as I said we
2:41:18want to automate the operation of every
2:41:20time we update a particular Row in any
2:41:22table we also want to update the updated
2:41:26field of that row so that we don't have
2:41:29to do it manually from our application
2:41:31code for that what we are doing we are
2:41:34creating a function in postgress we have
2:41:36the ability to create custom functions
2:41:39and we are creating a function and we
2:41:41are naming it something and we are
2:41:43seeing it returns a trigger and we are
2:41:45starting a transaction okay and what we
2:41:47are saying is take the row and the
2:41:50updated field of that row and update it
2:41:53to the current time stamp and return the
2:41:56new row whatever with the new value of
2:41:59the updated field and now we have a
2:42:00custom function that is ready to use
2:42:03okay next what we are doing we are
2:42:05creating Triggers on different different
2:42:06tables right we are taking all the
2:42:09different different tables users user
2:42:10profiles project tasks and we are
2:42:12creating Triggers on each table what we
2:42:14doing we are naming the trigger
2:42:16something so that it is easier to drop
2:42:18the trigger later on in in our down
2:42:21migrations okay and what you are doing
2:42:23you're saying every time we are doing
2:42:26some kind of update operations on this
2:42:28table go to that row whatever row is
2:42:31updated in that operation and execute
2:42:34this function and what this function
2:42:35does it takes the updated field and sets
2:42:38it to the current time stamp okay and
2:42:40with that setup what happens every time
2:42:42we do an update operation this will
2:42:45automatically update the updated at
2:42:47field for that r okay now that's pretty
2:42:51much it we are creating triggers for all
2:42:53the tables and in the down migrations we
2:42:55are deleting all the triggers we're
2:42:57deleting the function and we're deleting
2:43:00all the
2:43:00indexes that we created then we can go
2:43:04ahead and execute these migrations for
2:43:07that we can do dbate up and this is
2:43:10applied now going back to our table plus
2:43:14let's do that update operation again
2:43:17right so we remove this this this was
2:43:20our earlier update operation right and
2:43:24let's execute this say updated bio 3
2:43:28okay and let's apply it and go to this
2:43:32Row And now when you see the updated at
2:43:35field you can see that this is the
2:43:37current time when I am recording this
2:43:39video and this is the current date and
2:43:40time the time stem accurately matches so
2:43:43our trigger accurately worked right we
2:43:45did some kind of oper update operation
2:43:48on this particular row and this field is
2:43:50automatically updated and that's the use
2:43:53of triggers now with that we have
2:43:56created database queries for all these
2:43:59apis okay now going through each of
2:44:03these apis and creating a database query
2:44:04is going to take a lot of time at least
2:44:07a few hours more and I don't want to
2:44:09make this video longer than what it
2:44:12already is so you can go ahead and with
2:44:15all the uh reasoning that I have
2:44:18explained here and all the SQL Basics
2:44:21and the postgress basics that you have
2:44:22already learned you can go ahead and
2:44:24create the database queries for all
2:44:26these apis right and you can see how the
2:44:29join conditions work how the indexes are
2:44:31coming into place how the triggers are
2:44:33working etc etc etc right and that's
2:44:36pretty much all you need to know and of
2:44:39course that's not all you need to know
2:44:41but that's pretty much 80% of what you
2:44:44are going to be doing as a backend
2:44:45engineer while you are dealing with
2:44:47databases okay you're going to take apis
2:44:50and you're going to analyze what all
2:44:53payload is coming from the user and you
2:44:55have to construct a dynamic query
2:44:57depending on that you have to use
2:44:59parameterized queries to securely pass
2:45:02whatever user value that you have and
2:45:05you have to execute that query and you
2:45:07have to return the data right that's a
2:45:09very high level work through of what
2:45:11you're going to be doing as a backend
2:45:14engineer when it comes to databases of
2:45:17course there are a lot of other things
2:45:19but this pretty much covers on a very
2:45:21high level the most of the things that
2:45:23you'll be doing