WEBVTT 1 00:00:01.960 --> 00:00:03.011 So now that we've actually seen 2 00:00:03.011 --> 00:00:04.930 how to use the SQL language 3 00:00:04.930 --> 00:00:07.250 to work with SQLites databases, 4 00:00:07.250 --> 00:00:10.003 it's time to see how to do that in Python. 5 00:00:10.003 --> 00:00:13.491 So the Python SQLite3 module that's included with Python 6 00:00:13.491 --> 00:00:15.152 makes it really easy to create 7 00:00:15.152 --> 00:00:17.312 and use SQLite databases. 8 00:00:17.312 --> 00:00:18.912 So let's actually start off by creating 9 00:00:18.912 --> 00:00:20.997 this simple contacts database 10 00:00:20.997 --> 00:00:23.654 that we used in the SQL introduction. 11 00:00:23.654 --> 00:00:25.734 So I'm gonna create a new project here, 12 00:00:25.734 --> 00:00:28.251 Python project, obviously. 13 00:00:28.251 --> 00:00:31.584 And I'm going to call this one createDB. 14 00:00:35.911 --> 00:00:38.482 All right, and I'm going to create a new Python file 15 00:00:38.482 --> 00:00:42.020 by right-clicking the project, new Python file, 16 00:00:42.020 --> 00:00:44.770 and we'll call this one contacts. 17 00:00:46.042 --> 00:00:49.401 And we'll just go full screen here. 18 00:00:49.401 --> 00:00:50.741 Okay. 19 00:00:50.741 --> 00:00:53.870 So we start, going to start by importing the SQLite3 module, 20 00:00:53.870 --> 00:00:55.846 so we type import SQLite, 21 00:00:55.846 --> 00:00:57.875 and you can see that IntelliJ's found it for us, 22 00:00:57.875 --> 00:01:00.283 so we'll use the one that they recommend. 23 00:01:00.283 --> 00:01:02.837 Then we wanna create a connexion to the database. 24 00:01:02.837 --> 00:01:05.754 We'll do db equals sqlite3.connect. 25 00:01:07.838 --> 00:01:12.129 And we're gonna call this one contacts.sqlite. 26 00:01:12.129 --> 00:01:13.609 Now, I've said previously, 27 00:01:13.609 --> 00:01:16.238 that SQLite doesn't care what you call your database, 28 00:01:16.238 --> 00:01:19.118 as long as it's a valid file name, of course, 29 00:01:19.118 --> 00:01:20.838 but there's actually a reason here 30 00:01:20.838 --> 00:01:22.907 why I've used .sqlite as the name, 31 00:01:22.907 --> 00:01:25.009 and we'll see why that is later. 32 00:01:25.009 --> 00:01:29.487 So this line will create the contacts.sqlite database, 33 00:01:29.487 --> 00:01:30.918 if it doesn't already exist. 34 00:01:30.918 --> 00:01:33.156 Otherwise, it will open it for us. 35 00:01:33.156 --> 00:01:34.561 All right, so on the next line, now, 36 00:01:34.561 --> 00:01:36.744 we need to create a table, 37 00:01:36.744 --> 00:01:38.971 and we do that by passing a SQLite statement 38 00:01:38.971 --> 00:01:41.614 to the connexions execute function. 39 00:01:41.614 --> 00:01:42.781 So db.execute, 40 00:01:44.799 --> 00:01:45.941 then we type our SQL. 41 00:01:45.941 --> 00:01:48.024 So create table contacts, 42 00:01:51.488 --> 00:01:52.829 and left parentheses, 43 00:01:52.829 --> 00:01:54.940 we need a name and a type for each of the three fields. 44 00:01:54.940 --> 00:01:58.059 So name, space, text, comma, 45 00:01:58.059 --> 00:02:00.476 phone, space, integer, comma, 46 00:02:01.399 --> 00:02:04.578 and the last one's email, just text. 47 00:02:04.578 --> 00:02:08.010 The right parentheses, and then close the line off. 48 00:02:08.010 --> 00:02:10.178 All right, and we can do the similar thing 49 00:02:10.178 --> 00:02:12.679 by typing db.execute. 50 00:02:12.679 --> 00:02:14.818 This time we can use that to insert a line 51 00:02:14.818 --> 00:02:15.711 instead of record rows. 52 00:02:15.711 --> 00:02:17.544 Insert into, contacts, 53 00:02:21.271 --> 00:02:23.532 where we will put our three fields 54 00:02:23.532 --> 00:02:25.511 in parentheses, separated by commas. 55 00:02:25.511 --> 00:02:28.511 So name, obviously, phone. 56 00:02:28.511 --> 00:02:29.631 IntelliJ's trying to be helpful, 57 00:02:29.631 --> 00:02:32.183 but in this case, it's not really able to do much, 58 00:02:32.183 --> 00:02:36.114 because these values aren't coming from anywhere. 59 00:02:36.114 --> 00:02:37.493 And then values, but noticing 60 00:02:37.493 --> 00:02:39.151 how it's giving us the SQL here, 61 00:02:39.151 --> 00:02:41.130 so values, which is pretty cool. 62 00:02:41.130 --> 00:02:44.103 They want a parentheses, a parentheses here. 63 00:02:44.103 --> 00:02:45.282 They wanna use single quotes here, 64 00:02:45.282 --> 00:02:49.281 because we've got this string already using double quotes. 65 00:02:49.281 --> 00:02:51.698 So we need to, 6545678 there, 66 00:02:53.959 --> 00:02:55.792 and say tim@email.com. 67 00:02:58.070 --> 00:02:59.791 We need to make sure we've got a single quote, 68 00:02:59.791 --> 00:03:02.161 parentheses, a right parentheses, that is, 69 00:03:02.161 --> 00:03:06.328 double quote, and then right parentheses, which we have. 70 00:03:07.441 --> 00:03:09.911 And that should've been like that. 71 00:03:09.911 --> 00:03:12.340 All right, so that's our first line there to, 72 00:03:12.340 --> 00:03:15.468 could now insert a record into the contacts table. 73 00:03:15.468 --> 00:03:16.451 Now I'm gonna insert another row, 74 00:03:16.451 --> 00:03:18.614 but this time, watch what happens as I type. 75 00:03:18.614 --> 00:03:22.031 So db.execute, and double quotes, insert. 76 00:03:23.624 --> 00:03:25.875 Now, what should happen, which does sometimes, 77 00:03:25.875 --> 00:03:29.246 is the IntelliJ lookup will actually start helping us 78 00:03:29.246 --> 00:03:32.014 by giving the, sort of giving us some hints 79 00:03:32.014 --> 00:03:33.486 as to what commands to use, 80 00:03:33.486 --> 00:03:34.319 but you can see in this case, 81 00:03:34.319 --> 00:03:36.323 it hasn't done anything at this point for us, 82 00:03:36.323 --> 00:03:37.333 which isn't very nice. 83 00:03:37.333 --> 00:03:39.343 I thought it might kick in and do that for us, 84 00:03:39.343 --> 00:03:40.733 but we'll try typing a bit more 85 00:03:40.733 --> 00:03:42.721 and see whether it comes back into play again. 86 00:03:42.721 --> 00:03:44.721 So insert into contacts. 87 00:03:46.263 --> 00:03:47.333 Now that was actually trying to give us 88 00:03:47.333 --> 00:03:49.063 the SQL command there, that lookup, 89 00:03:49.063 --> 00:03:51.600 but if I keep typing, 90 00:03:51.600 --> 00:03:55.760 and we'll just go with the three fields, name, phone. 91 00:03:55.760 --> 00:03:57.789 Actually, this time what we'll do, 92 00:03:57.789 --> 00:03:59.706 let's just delete that. 93 00:04:01.439 --> 00:04:03.008 And put a space and put values, 94 00:04:03.008 --> 00:04:05.257 and noticing how it's come up and 95 00:04:05.257 --> 00:04:08.258 put in the keyword values for us automatically. 96 00:04:08.258 --> 00:04:10.826 And I'll just enter the values that we wanna use here, 97 00:04:10.826 --> 00:04:14.409 which will be Brian in single quotes, 1234, 98 00:04:16.626 --> 00:04:19.543 and brian@myemail, email.com again, 99 00:04:22.129 --> 00:04:24.439 separated by single parentheses, 100 00:04:24.439 --> 00:04:26.369 and the whole thing's got parentheses around it 101 00:04:26.369 --> 00:04:27.319 for the value statement, 102 00:04:27.319 --> 00:04:29.669 and then we've got a double quote to close off the string 103 00:04:29.669 --> 00:04:33.759 and a right parentheses to close off the execute function. 104 00:04:33.759 --> 00:04:35.759 Now, we're probably seeing some warnings over here, 105 00:04:35.759 --> 00:04:38.458 so we come over and have a look. 106 00:04:38.458 --> 00:04:41.089 No data sources are configured. 107 00:04:41.089 --> 00:04:44.129 Basically, IntelliJ doesn't have a schema for our database, 108 00:04:44.129 --> 00:04:45.388 so it can't recognise the names 109 00:04:45.388 --> 00:04:46.857 of the columns that we're using, 110 00:04:46.857 --> 00:04:48.844 but don't worry about these warnings for the moment. 111 00:04:48.844 --> 00:04:51.351 We'll come back to those a little bit later. 112 00:04:51.351 --> 00:04:52.609 The last thing I wanna do now, 113 00:04:52.609 --> 00:04:55.031 before we actually run this programme for the first time, 114 00:04:55.031 --> 00:04:57.971 is to close off our database connexions. 115 00:04:57.971 --> 00:05:01.971 We do that with db.close on line eight, like so. 116 00:05:02.886 --> 00:05:04.278 All right, so it should be we've got no errors, 117 00:05:04.278 --> 00:05:05.857 which we haven't, on the screen here. 118 00:05:05.857 --> 00:05:07.684 We can actually run this programme now, 119 00:05:07.684 --> 00:05:09.166 and we should have a table created 120 00:05:09.166 --> 00:05:11.595 with two rows added. 121 00:05:11.595 --> 00:05:13.684 Then we're gonna run it. 122 00:05:13.684 --> 00:05:14.616 We don't get any output, 123 00:05:14.616 --> 00:05:17.630 which is generally a good sign with MySQL 124 00:05:17.630 --> 00:05:18.510 that things have worked. 125 00:05:18.510 --> 00:05:20.044 And I'll just put this down the bottom, 126 00:05:20.044 --> 00:05:22.315 so we can see the output. 127 00:05:22.315 --> 00:05:25.414 All right, so looks like things have worked okay there. 128 00:05:25.414 --> 00:05:28.630 And to verify it, we could switch over to a terminal 129 00:05:28.630 --> 00:05:31.045 and use the SQLite3 command line shell 130 00:05:31.045 --> 00:05:32.184 to check the database, 131 00:05:32.184 --> 00:05:33.987 but we've already seen how to do that, 132 00:05:33.987 --> 00:05:38.365 so let's actually see how to query our database from Python. 133 00:05:38.365 --> 00:05:40.152 Now, there's two ways we can do that. 134 00:05:40.152 --> 00:05:42.664 The usual way, and the way that's common to other languages, 135 00:05:42.664 --> 00:05:46.161 such as Java, for example, is to use a cursor. 136 00:05:46.161 --> 00:05:48.141 Now cursors can be very useful, 137 00:05:48.141 --> 00:05:49.941 so I'm gonna explain about them 138 00:05:49.941 --> 00:05:52.141 before showing you a shortcut way 139 00:05:52.141 --> 00:05:54.962 of doing some of the same things from our connexion. 140 00:05:54.962 --> 00:05:57.922 First, though, we've actually got a problem here. 141 00:05:57.922 --> 00:05:59.912 Now, we can't run the programme again, 142 00:05:59.912 --> 00:06:02.693 because the create table command's going to fail 143 00:06:02.693 --> 00:06:05.091 if we try to execute it again. 144 00:06:05.091 --> 00:06:06.448 Now, we could write code to check 145 00:06:06.448 --> 00:06:08.321 if the table already exists, 146 00:06:08.321 --> 00:06:11.281 but the SQL language has got a slightly different form 147 00:06:11.281 --> 00:06:12.556 of the create table command 148 00:06:12.556 --> 00:06:14.869 that actually copes with this situation. 149 00:06:14.869 --> 00:06:16.881 So we come up here to line four, 150 00:06:16.881 --> 00:06:20.706 and we actually put in some extra wording. 151 00:06:20.706 --> 00:06:22.839 So if, and notice how I've just typed I, 152 00:06:22.839 --> 00:06:24.468 and it's now helpfully saying, yeah, 153 00:06:24.468 --> 00:06:26.988 if not exists, I can press enter or tab there, 154 00:06:26.988 --> 00:06:29.529 and it helpfully adds that to our code. 155 00:06:29.529 --> 00:06:30.689 So as you can imagine, 156 00:06:30.689 --> 00:06:32.768 if the table doesn't already exist, 157 00:06:32.768 --> 00:06:34.068 it's going to create it, 158 00:06:34.068 --> 00:06:35.773 and if it does exist, 159 00:06:35.773 --> 00:06:37.508 it's going to not try and recreate it again, 160 00:06:37.508 --> 00:06:40.979 which is exactly what we want to actually happen here. 161 00:06:40.979 --> 00:06:42.889 All right, so now we can test our code. 162 00:06:42.889 --> 00:06:45.180 So I'm gonna add the code to create a cursor 163 00:06:45.180 --> 00:06:47.464 and use it to run a select query. 164 00:06:47.464 --> 00:06:48.601 And I'll also close the cursor 165 00:06:48.601 --> 00:06:50.759 when we're done with it, to be consistent. 166 00:06:50.759 --> 00:06:53.550 So let's actually start here on line eight. 167 00:06:53.550 --> 00:06:57.217 And we're gonna put cursor equals db.cursor. 168 00:06:59.060 --> 00:07:01.420 And then we want to execute a select query, 169 00:07:01.420 --> 00:07:03.337 so it's cursor.execute, 170 00:07:05.220 --> 00:07:08.580 noting how cursors are executed at db.execute now, 171 00:07:08.580 --> 00:07:12.413 and let's just do a select star from contacts. 172 00:07:14.740 --> 00:07:17.776 And then we can put for row 173 00:07:17.776 --> 00:07:20.443 in cursor, colon, and print row. 174 00:07:24.144 --> 00:07:27.144 And then we wanna do a cursor.close. 175 00:07:28.344 --> 00:07:32.154 All right, so if we run this programme now, 176 00:07:32.154 --> 00:07:34.063 we actually get our two rows printed, as you can see, 177 00:07:34.063 --> 00:07:37.635 on the bottom of the screen in the output window. 178 00:07:37.635 --> 00:07:39.635 Now each row is printed as a tuple 179 00:07:39.635 --> 00:07:41.835 containing a value for each of the columns 180 00:07:41.835 --> 00:07:43.126 in the database. 181 00:07:43.126 --> 00:07:45.926 Now, a database cursor is iterable, 182 00:07:45.926 --> 00:07:48.425 so we can just use a for loop to iterate over the cursor 183 00:07:48.425 --> 00:07:51.268 and print each row, as we've actually done. 184 00:07:51.268 --> 00:07:53.680 And what we could also do, if we wanted to, 185 00:07:53.680 --> 00:07:56.203 we can unpack the tuples as we go, 186 00:07:56.203 --> 00:07:59.007 so we could slightly change the syntax there. 187 00:07:59.007 --> 00:08:01.111 Instead of just for row in cursor, 188 00:08:01.111 --> 00:08:02.778 we can put for name, 189 00:08:04.787 --> 00:08:06.704 phone, email in cursor. 190 00:08:08.202 --> 00:08:11.464 And then we can do print name, 191 00:08:11.464 --> 00:08:13.547 print phone, print email. 192 00:08:16.864 --> 00:08:20.197 And then we can do a separator times 20. 193 00:08:22.053 --> 00:08:24.886 So if we run that revised programme, 194 00:08:25.802 --> 00:08:28.177 you can see we've got our records 195 00:08:28.177 --> 00:08:31.253 unpacked, down the bottom in the output window. 196 00:08:31.253 --> 00:08:32.461 Now one thing you may have noticed 197 00:08:32.461 --> 00:08:34.671 is that I'm not terminating the SQL commands 198 00:08:34.671 --> 00:08:36.493 with a semi-colon. 199 00:08:36.493 --> 00:08:37.832 Now, they're not generally needed 200 00:08:37.832 --> 00:08:40.841 when using the Python 3 SQLite3 module, 201 00:08:40.841 --> 00:08:44.671 and in keeping with the, with the Python philosophy, 202 00:08:44.671 --> 00:08:47.024 you'll find they're generally not used. 203 00:08:47.024 --> 00:08:48.984 In fact, they can often get in the way 204 00:08:48.984 --> 00:08:51.072 if you store a select statement in a string, 205 00:08:51.072 --> 00:08:53.802 and later concatenate a where clause at the end. 206 00:08:53.802 --> 00:08:55.024 You don't wanna have to search for 207 00:08:55.024 --> 00:08:56.661 and remove a trailing semi-colon 208 00:08:56.661 --> 00:08:58.861 at the end of the select statement. 209 00:08:58.861 --> 00:09:00.581 So my recommendation is generally, 210 00:09:00.581 --> 00:09:04.434 don't use semi-colons when using SQL in Python. 211 00:09:04.434 --> 00:09:05.300 (chuckles) I know at this point, 212 00:09:05.300 --> 00:09:06.928 I spent a couple of lectures 213 00:09:06.928 --> 00:09:09.158 getting you into the habit of actually using them, 214 00:09:09.158 --> 00:09:11.908 but they are needed when using SQL in most environments, 215 00:09:11.908 --> 00:09:14.249 so it was a good habit to develop generally, 216 00:09:14.249 --> 00:09:16.849 but you can now relax and stop adding semi-colons 217 00:09:16.849 --> 00:09:19.910 in your SQL statements in Python. 218 00:09:19.910 --> 00:09:23.702 Okay, so our cursor code uses the cursor's execute method 219 00:09:23.702 --> 00:09:26.852 to execute the SQL against the database 220 00:09:26.852 --> 00:09:28.117 and return something that behaves 221 00:09:28.117 --> 00:09:29.959 very much like a list. 222 00:09:29.959 --> 00:09:32.452 So we can iterate over it to process each row, 223 00:09:32.452 --> 00:09:35.348 but it's really not a list. 224 00:09:35.348 --> 00:09:37.721 And if you think about it, a database table 225 00:09:37.721 --> 00:09:40.539 could contain, you know, literally billions of rows. 226 00:09:40.539 --> 00:09:42.380 So if the cursor tried to load them all 227 00:09:42.380 --> 00:09:44.300 into a list in memory, 228 00:09:44.300 --> 00:09:47.270 it's highly likely we'd run out of memory. 229 00:09:47.270 --> 00:09:49.908 So a cursor is what's called a generator. 230 00:09:49.908 --> 00:09:52.729 Now, I'm not gonna go into detail about those now, 231 00:09:52.729 --> 00:09:55.379 but a generator is basically an iterable 232 00:09:55.379 --> 00:09:57.939 that works by generating the next value 233 00:09:57.939 --> 00:10:00.611 each time it's used in Python. 234 00:10:00.611 --> 00:10:02.960 You can create an iterable object 235 00:10:02.960 --> 00:10:06.658 that will return every single possible integer number. 236 00:10:06.658 --> 00:10:07.877 So you could count to infinity 237 00:10:07.877 --> 00:10:09.295 without running out of memory. 238 00:10:09.295 --> 00:10:11.146 Time may be against you, of course, 239 00:10:11.146 --> 00:10:13.746 but memory wouldn't be a problem. 240 00:10:13.746 --> 00:10:17.075 So when our code iterates over the cursor, 241 00:10:17.075 --> 00:10:19.197 it returns the next row from the database 242 00:10:19.197 --> 00:10:22.136 but doesn't actually keep track of previous rows. 243 00:10:22.136 --> 00:10:24.197 Now because it's not really a list, 244 00:10:24.197 --> 00:10:26.664 there's no way to go back to previous records, 245 00:10:26.664 --> 00:10:29.493 and that explains why this next bit of code 246 00:10:29.493 --> 00:10:31.943 doesn't do what we might expect. 247 00:10:31.943 --> 00:10:32.864 And to show you what I mean, 248 00:10:32.864 --> 00:10:36.136 I'm going to actually take a copy of our for loop 249 00:10:36.136 --> 00:10:38.445 up to and including the separator, 250 00:10:38.445 --> 00:10:42.164 and I'm gonna paste that down here, 251 00:10:42.164 --> 00:10:43.626 put another space there. 252 00:10:43.626 --> 00:10:45.127 So looking at this, this, well actually, 253 00:10:45.127 --> 00:10:47.127 let's just run it first. 254 00:10:48.823 --> 00:10:49.887 So it's looking at the output 255 00:10:49.887 --> 00:10:52.959 at the bottom of the screen there. 256 00:10:52.959 --> 00:10:56.030 You may have expected the rows to be printed out again, 257 00:10:56.030 --> 00:10:58.050 but when we get to the second for loop, 258 00:10:58.050 --> 00:11:01.255 the cursors actually run out of rows, so nothing's printed. 259 00:11:01.255 --> 00:11:03.628 The only way to get our cursor to start again 260 00:11:03.628 --> 00:11:06.009 is to actually run the query again. 261 00:11:06.009 --> 00:11:09.139 And what that does, it makes cursors very efficient 262 00:11:09.139 --> 00:11:11.110 when reading data from databases, 263 00:11:11.110 --> 00:11:12.489 because they don't use loads of memory 264 00:11:12.489 --> 00:11:14.379 storing all the records. 265 00:11:14.379 --> 00:11:15.660 Now, sometimes, you may actually want 266 00:11:15.660 --> 00:11:17.809 the entire dataset in a single list, 267 00:11:17.809 --> 00:11:19.206 and rather than using a for loop 268 00:11:19.206 --> 00:11:20.350 to build up your own list, 269 00:11:20.350 --> 00:11:23.340 you can actually use the fetchall method. 270 00:11:23.340 --> 00:11:24.390 All right, so I'm actually gonna delete 271 00:11:24.390 --> 00:11:26.636 that second for loop, 272 00:11:26.636 --> 00:11:29.084 'cause it's not actually doing anything. 273 00:11:29.084 --> 00:11:31.957 And let's actually go above that, that loop. 274 00:11:31.957 --> 00:11:34.266 We'll actually put a space here, actually, 275 00:11:34.266 --> 00:11:36.079 after the execute, anyway, to just 276 00:11:36.079 --> 00:11:37.697 free things up a little bit. 277 00:11:37.697 --> 00:11:39.843 But let's actually just add something to that again, 278 00:11:39.843 --> 00:11:42.343 and put print cursor.fetchall. 279 00:11:48.337 --> 00:11:51.754 All right, so now if I actually run this, 280 00:11:53.724 --> 00:11:56.082 you can see that the fetchall has returned a list 281 00:11:56.082 --> 00:11:59.433 containing a tuple for each row in the database. 282 00:11:59.433 --> 00:12:00.931 So it is possible to get all the rows 283 00:12:00.931 --> 00:12:02.843 from a database into a list, 284 00:12:02.843 --> 00:12:04.991 and then you can actually move backwards and forwards 285 00:12:04.991 --> 00:12:07.043 through the items in the list. 286 00:12:07.043 --> 00:12:08.291 Because all the data's being retrieved 287 00:12:08.291 --> 00:12:10.481 from the cursor by the fetchall method, 288 00:12:10.481 --> 00:12:13.592 our for loop, though, in this particular case, on line 13, 289 00:12:13.592 --> 00:12:15.512 hasn't got anything to print. 290 00:12:15.512 --> 00:12:17.192 Now, there's also a fetchone method 291 00:12:17.192 --> 00:12:20.322 that returns the next row in the cursor. 292 00:12:20.322 --> 00:12:21.372 And to get that to work, 293 00:12:21.372 --> 00:12:23.772 we'll have to come in out the call the fetchall. 294 00:12:23.772 --> 00:12:25.535 So we'll do that first. 295 00:12:25.535 --> 00:12:29.269 And then we can actually change our code a little bit, 296 00:12:29.269 --> 00:12:33.102 up here, and we can put print cursor.fetchone. 297 00:12:37.087 --> 00:12:39.847 Let's just duplicate that another two times. 298 00:12:39.847 --> 00:12:42.180 And if we actually run this, 299 00:12:43.559 --> 00:12:45.167 so you can see what happened there. 300 00:12:45.167 --> 00:12:47.866 The first two times, it returned what was the current row, 301 00:12:47.866 --> 00:12:49.336 then moved on to the next one, 302 00:12:49.336 --> 00:12:53.336 but the third call, call to fetchone, results in none, 303 00:12:53.336 --> 00:12:56.185 and that's because there's no rows left to fetch. 304 00:12:56.185 --> 00:12:58.277 So fetchone is quite useful, 305 00:12:58.277 --> 00:13:00.067 and we're gonna be using that a bit later, 306 00:13:00.067 --> 00:13:02.011 when we wanna retrieve a single row 307 00:13:02.011 --> 00:13:03.654 based on its ID. 308 00:13:03.654 --> 00:13:05.871 All right, so I'm gonna finish the video here now. 309 00:13:05.871 --> 00:13:07.370 In the next video, we're gonna look at that shortcut 310 00:13:07.370 --> 00:13:09.423 that I mentioned earlier in this video, 311 00:13:09.423 --> 00:13:11.215 so I'll see you in the next video.