1
00:00:05,100 --> 00:00:06,150
So now that we've actually seen

2
00:00:06,150 --> 00:00:08,070
how to use the SQL language

3
00:00:08,070 --> 00:00:10,390
to work with SQLites databases,

4
00:00:10,390 --> 00:00:13,140
it's time to see how to do that in Python.

5
00:00:13,140 --> 00:00:16,630
So the Python SQLite3 module that's included with Python

6
00:00:16,630 --> 00:00:18,290
makes it really easy to create

7
00:00:18,290 --> 00:00:20,450
and use SQLite databases.

8
00:00:20,450 --> 00:00:22,050
So let's actually start off by creating

9
00:00:22,050 --> 00:00:24,130
this simple contacts database

10
00:00:24,130 --> 00:00:26,790
that we used in the SQL introduction.

11
00:00:26,790 --> 00:00:28,870
So I'm gonna create a new project here,

12
00:00:28,870 --> 00:00:31,390
Python project, obviously.

13
00:00:31,390 --> 00:00:34,720
And I'm going to call this one createDB.

14
00:00:39,050 --> 00:00:41,620
All right, and I'm going to create a new Python file

15
00:00:41,620 --> 00:00:45,160
by right-clicking the project, new Python file,

16
00:00:45,160 --> 00:00:47,910
and we'll call this one contacts.

17
00:00:49,180 --> 00:00:52,540
And we'll just go full screen here.

18
00:00:52,540 --> 00:00:53,880
Okay.

19
00:00:53,880 --> 00:00:57,010
So we start, going to start by importing the SQLite3 module,

20
00:00:57,010 --> 00:00:58,980
so we type import SQLite,

21
00:00:58,980 --> 00:01:01,010
and you can see that IntelliJ's found it for us,

22
00:01:01,010 --> 00:01:03,420
so we'll use the one that they recommend.

23
00:01:03,420 --> 00:01:05,970
Then we wanna create a connexion to the database.

24
00:01:05,970 --> 00:01:08,890
We'll do db equals sqlite3.connect.

25
00:01:10,970 --> 00:01:15,260
And we're gonna call this one contacts.sqlite.

26
00:01:15,260 --> 00:01:16,740
Now, I've said previously,

27
00:01:16,740 --> 00:01:19,370
that SQLite doesn't care what you call your database,

28
00:01:19,370 --> 00:01:22,250
as long as it's a valid file name, of course,

29
00:01:22,250 --> 00:01:23,970
but there's actually a reason here

30
00:01:23,970 --> 00:01:26,040
why I've used .sqlite as the name,

31
00:01:26,040 --> 00:01:28,140
and we'll see why that is later.

32
00:01:28,140 --> 00:01:32,620
So this line will create the contacts.sqlite database,

33
00:01:32,620 --> 00:01:34,050
if it doesn't already exist.

34
00:01:34,050 --> 00:01:36,290
Otherwise, it will open it for us.

35
00:01:36,290 --> 00:01:37,700
All right, so on the next line, now,

36
00:01:37,700 --> 00:01:39,880
we need to create a table,

37
00:01:39,880 --> 00:01:42,110
and we do that by passing a SQLite statement

38
00:01:42,110 --> 00:01:44,750
to the connexions execute function.

39
00:01:44,750 --> 00:01:45,920
So db.execute,

40
00:01:47,930 --> 00:01:49,080
then we type our SQL.

41
00:01:49,080 --> 00:01:51,160
So create table contacts,

42
00:01:54,620 --> 00:01:55,960
and left parentheses,

43
00:01:55,960 --> 00:01:58,080
we need a name and a type for each of the three fields.

44
00:01:58,080 --> 00:02:01,190
So name, space, text, comma,

45
00:02:01,190 --> 00:02:03,610
phone, space, integer, comma,

46
00:02:04,530 --> 00:02:07,710
and the last one's email, just text.

47
00:02:07,710 --> 00:02:11,150
The right parentheses, and then close the line off.

48
00:02:11,150 --> 00:02:13,310
All right, and we can do the similar thing

49
00:02:13,310 --> 00:02:15,810
by typing db.execute.

50
00:02:15,810 --> 00:02:17,950
This time we can use that to insert a line

51
00:02:17,950 --> 00:02:18,850
instead of record rows.

52
00:02:18,850 --> 00:02:20,680
Insert into, contacts,

53
00:02:24,410 --> 00:02:26,670
where we will put our three fields

54
00:02:26,670 --> 00:02:28,650
in parentheses, separated by commas.

55
00:02:28,650 --> 00:02:31,650
So name, obviously, phone.

56
00:02:31,650 --> 00:02:32,770
IntelliJ's trying to be helpful,

57
00:02:32,770 --> 00:02:35,320
but in this case, it's not really able to do much,

58
00:02:35,320 --> 00:02:39,250
because these values aren't coming from anywhere.

59
00:02:39,250 --> 00:02:40,630
And then values, but noticing

60
00:02:40,630 --> 00:02:42,290
how it's giving us the SQL here,

61
00:02:42,290 --> 00:02:44,270
so values, which is pretty cool.

62
00:02:44,270 --> 00:02:47,240
They want a parentheses, a parentheses here.

63
00:02:47,240 --> 00:02:48,420
They wanna use single quotes here,

64
00:02:48,420 --> 00:02:52,420
because we've got this string already using double quotes.

65
00:02:52,420 --> 00:02:54,830
So we need to, 6545678 there,

66
00:02:57,090 --> 00:02:58,930
and say tim@email.com.

67
00:03:01,210 --> 00:03:02,930
We need to make sure we've got a single quote,

68
00:03:02,930 --> 00:03:05,300
parentheses, a right parentheses, that is,

69
00:03:05,300 --> 00:03:09,460
double quote, and then right parentheses, which we have.

70
00:03:10,580 --> 00:03:13,050
And that should've been like that.

71
00:03:13,050 --> 00:03:15,480
All right, so that's our first line there to,

72
00:03:15,480 --> 00:03:18,600
could now insert a record into the contacts table.

73
00:03:18,600 --> 00:03:19,590
Now I'm gonna insert another row,

74
00:03:19,590 --> 00:03:21,750
but this time, watch what happens as I type.

75
00:03:21,750 --> 00:03:25,170
So db.execute, and double quotes, insert.

76
00:03:26,760 --> 00:03:29,010
Now, what should happen, which does sometimes,

77
00:03:29,010 --> 00:03:32,380
is the IntelliJ lookup will actually start helping us

78
00:03:32,380 --> 00:03:35,150
by giving the, sort of giving us some hints

79
00:03:35,150 --> 00:03:36,620
as to what commands to use,

80
00:03:36,620 --> 00:03:37,450
but you can see in this case,

81
00:03:37,450 --> 00:03:39,460
it hasn't done anything at this point for us,

82
00:03:39,460 --> 00:03:40,470
which isn't very nice.

83
00:03:40,470 --> 00:03:42,480
I thought it might kick in and do that for us,

84
00:03:42,480 --> 00:03:43,870
but we'll try typing a bit more

85
00:03:43,870 --> 00:03:45,860
and see whether it comes back into play again.

86
00:03:45,860 --> 00:03:47,860
So insert into contacts.

87
00:03:49,400 --> 00:03:50,470
Now that was actually trying to give us

88
00:03:50,470 --> 00:03:52,200
the SQL command there, that lookup,

89
00:03:52,200 --> 00:03:54,740
but if I keep typing,

90
00:03:54,740 --> 00:03:58,900
and we'll just go with the three fields, name, phone.

91
00:03:58,900 --> 00:04:00,920
Actually, this time what we'll do,

92
00:04:00,920 --> 00:04:02,840
let's just delete that.

93
00:04:04,570 --> 00:04:06,140
And put a space and put values,

94
00:04:06,140 --> 00:04:08,390
and noticing how it's come up and

95
00:04:08,390 --> 00:04:11,390
put in the keyword values for us automatically.

96
00:04:11,390 --> 00:04:13,960
And I'll just enter the values that we wanna use here,

97
00:04:13,960 --> 00:04:17,540
which will be Brian in single quotes, 1234,

98
00:04:19,760 --> 00:04:22,680
and brian@myemail, email.com again,

99
00:04:25,260 --> 00:04:27,570
separated by single parentheses,

100
00:04:27,570 --> 00:04:29,500
and the whole thing's got parentheses around it

101
00:04:29,500 --> 00:04:30,450
for the value statement,

102
00:04:30,450 --> 00:04:32,800
and then we've got a double quote to close off the string

103
00:04:32,800 --> 00:04:36,890
and a right parentheses to close off the execute function.

104
00:04:36,890 --> 00:04:38,890
Now, we're probably seeing some warnings over here,

105
00:04:38,890 --> 00:04:41,590
so we come over and have a look.

106
00:04:41,590 --> 00:04:44,220
No data sources are configured.

107
00:04:44,220 --> 00:04:47,260
Basically, IntelliJ doesn't have a schema for our database,

108
00:04:47,260 --> 00:04:48,520
so it can't recognise the names

109
00:04:48,520 --> 00:04:49,990
of the columns that we're using,

110
00:04:49,990 --> 00:04:51,980
but don't worry about these warnings for the moment.

111
00:04:51,980 --> 00:04:54,490
We'll come back to those a little bit later.

112
00:04:54,490 --> 00:04:55,740
The last thing I wanna do now,

113
00:04:55,740 --> 00:04:58,170
before we actually run this programme for the first time,

114
00:04:58,170 --> 00:05:01,110
is to close off our database connexions.

115
00:05:01,110 --> 00:05:05,110
We do that with db.close on line eight, like so.

116
00:05:06,020 --> 00:05:07,410
All right, so it should be we've got no errors,

117
00:05:07,410 --> 00:05:08,990
which we haven't, on the screen here.

118
00:05:08,990 --> 00:05:10,820
We can actually run this programme now,

119
00:05:10,820 --> 00:05:12,300
and we should have a table created

120
00:05:12,300 --> 00:05:14,730
with two rows added.

121
00:05:14,730 --> 00:05:16,820
Then we're gonna run it.

122
00:05:16,820 --> 00:05:17,750
We don't get any output,

123
00:05:17,750 --> 00:05:20,770
which is generally a good sign with MySQL

124
00:05:20,770 --> 00:05:21,650
that things have worked.

125
00:05:21,650 --> 00:05:23,180
And I'll just put this down the bottom,

126
00:05:23,180 --> 00:05:25,450
so we can see the output.

127
00:05:25,450 --> 00:05:28,550
All right, so looks like things have worked okay there.

128
00:05:28,550 --> 00:05:31,770
And to verify it, we could switch over to a terminal

129
00:05:31,770 --> 00:05:34,180
and use the SQLite3 command line shell

130
00:05:34,180 --> 00:05:35,320
to check the database,

131
00:05:35,320 --> 00:05:37,120
but we've already seen how to do that,

132
00:05:37,120 --> 00:05:41,500
so let's actually see how to query our database from Python.

133
00:05:41,500 --> 00:05:43,290
Now, there's two ways we can do that.

134
00:05:43,290 --> 00:05:45,800
The usual way, and the way that's common to other languages,

135
00:05:45,800 --> 00:05:49,300
such as Java, for example, is to use a cursor.

136
00:05:49,300 --> 00:05:51,280
Now cursors can be very useful,

137
00:05:51,280 --> 00:05:53,080
so I'm gonna explain about them

138
00:05:53,080 --> 00:05:55,280
before showing you a shortcut way

139
00:05:55,280 --> 00:05:58,100
of doing some of the same things from our connexion.

140
00:05:58,100 --> 00:06:01,060
First, though, we've actually got a problem here.

141
00:06:01,060 --> 00:06:03,050
Now, we can't run the programme again,

142
00:06:03,050 --> 00:06:05,830
because the create table command's going to fail

143
00:06:05,830 --> 00:06:08,230
if we try to execute it again.

144
00:06:08,230 --> 00:06:09,580
Now, we could write code to check

145
00:06:09,580 --> 00:06:11,460
if the table already exists,

146
00:06:11,460 --> 00:06:14,420
but the SQL language has got a slightly different form

147
00:06:14,420 --> 00:06:15,690
of the create table command

148
00:06:15,690 --> 00:06:18,000
that actually copes with this situation.

149
00:06:18,000 --> 00:06:20,020
So we come up here to line four,

150
00:06:20,020 --> 00:06:23,840
and we actually put in some extra wording.

151
00:06:23,840 --> 00:06:25,970
So if, and notice how I've just typed I,

152
00:06:25,970 --> 00:06:27,600
and it's now helpfully saying, yeah,

153
00:06:27,600 --> 00:06:30,120
if not exists, I can press enter or tab there,

154
00:06:30,120 --> 00:06:32,660
and it helpfully adds that to our code.

155
00:06:32,660 --> 00:06:33,820
So as you can imagine,

156
00:06:33,820 --> 00:06:35,900
if the table doesn't already exist,

157
00:06:35,900 --> 00:06:37,200
it's going to create it,

158
00:06:37,200 --> 00:06:38,910
and if it does exist,

159
00:06:38,910 --> 00:06:40,640
it's going to not try and recreate it again,

160
00:06:40,640 --> 00:06:44,110
which is exactly what we want to actually happen here.

161
00:06:44,110 --> 00:06:46,020
All right, so now we can test our code.

162
00:06:46,020 --> 00:06:48,320
So I'm gonna add the code to create a cursor

163
00:06:48,320 --> 00:06:50,600
and use it to run a select query.

164
00:06:50,600 --> 00:06:51,740
And I'll also close the cursor

165
00:06:51,740 --> 00:06:53,890
when we're done with it, to be consistent.

166
00:06:53,890 --> 00:06:56,690
So let's actually start here on line eight.

167
00:06:56,690 --> 00:07:00,350
And we're gonna put cursor equals db.cursor.

168
00:07:02,200 --> 00:07:04,560
And then we want to execute a select query,

169
00:07:04,560 --> 00:07:06,470
so it's cursor.execute,

170
00:07:08,360 --> 00:07:11,720
noting how cursors are executed at db.execute now,

171
00:07:11,720 --> 00:07:15,550
and let's just do a select star from contacts.

172
00:07:17,880 --> 00:07:20,910
And then we can put for row

173
00:07:20,910 --> 00:07:23,580
in cursor, colon, and print row.

174
00:07:27,280 --> 00:07:30,280
And then we wanna do a cursor.close.

175
00:07:31,480 --> 00:07:35,290
All right, so if we run this programme now,

176
00:07:35,290 --> 00:07:37,200
we actually get our two rows printed, as you can see,

177
00:07:37,200 --> 00:07:40,770
on the bottom of the screen in the output window.

178
00:07:40,770 --> 00:07:42,770
Now each row is printed as a tuple

179
00:07:42,770 --> 00:07:44,970
containing a value for each of the columns

180
00:07:44,970 --> 00:07:46,260
in the database.

181
00:07:46,260 --> 00:07:49,060
Now, a database cursor is iterable,

182
00:07:49,060 --> 00:07:51,560
so we can just use a for loop to iterate over the cursor

183
00:07:51,560 --> 00:07:54,400
and print each row, as we've actually done.

184
00:07:54,400 --> 00:07:56,820
And what we could also do, if we wanted to,

185
00:07:56,820 --> 00:07:59,340
we can unpack the tuples as we go,

186
00:07:59,340 --> 00:08:02,140
so we could slightly change the syntax there.

187
00:08:02,140 --> 00:08:04,250
Instead of just for row in cursor,

188
00:08:04,250 --> 00:08:05,910
we can put for name,

189
00:08:07,920 --> 00:08:09,840
phone, email in cursor.

190
00:08:11,340 --> 00:08:14,600
And then we can do print name,

191
00:08:14,600 --> 00:08:16,680
print phone, print email.

192
00:08:20,000 --> 00:08:23,330
And then we can do a separator times 20.

193
00:08:25,190 --> 00:08:28,020
So if we run that revised programme,

194
00:08:28,940 --> 00:08:31,310
you can see we've got our records

195
00:08:31,310 --> 00:08:34,390
unpacked, down the bottom in the output window.

196
00:08:34,390 --> 00:08:35,600
Now one thing you may have noticed

197
00:08:35,600 --> 00:08:37,809
is that I'm not terminating the SQL commands

198
00:08:37,809 --> 00:08:39,630
with a semi-colon.

199
00:08:39,630 --> 00:08:40,970
Now, they're not generally needed

200
00:08:40,970 --> 00:08:43,980
when using the Python 3 SQLite3 module,

201
00:08:43,980 --> 00:08:47,810
and in keeping with the, with the Python philosophy,

202
00:08:47,810 --> 00:08:50,160
you'll find they're generally not used.

203
00:08:50,160 --> 00:08:52,120
In fact, they can often get in the way

204
00:08:52,120 --> 00:08:54,210
if you store a select statement in a string,

205
00:08:54,210 --> 00:08:56,940
and later concatenate a where clause at the end.

206
00:08:56,940 --> 00:08:58,160
You don't wanna have to search for

207
00:08:58,160 --> 00:08:59,800
and remove a trailing semi-colon

208
00:08:59,800 --> 00:09:02,000
at the end of the select statement.

209
00:09:02,000 --> 00:09:03,720
So my recommendation is generally,

210
00:09:03,720 --> 00:09:07,570
don't use semi-colons when using SQL in Python.

211
00:09:07,570 --> 00:09:08,440
(chuckles) I know at this point,

212
00:09:08,440 --> 00:09:10,060
I spent a couple of lectures

213
00:09:10,060 --> 00:09:12,290
getting you into the habit of actually using them,

214
00:09:12,290 --> 00:09:15,040
but they are needed when using SQL in most environments,

215
00:09:15,040 --> 00:09:17,380
so it was a good habit to develop generally,

216
00:09:17,380 --> 00:09:19,980
but you can now relax and stop adding semi-colons

217
00:09:19,980 --> 00:09:23,050
in your SQL statements in Python.

218
00:09:23,050 --> 00:09:26,840
Okay, so our cursor code uses the cursor's execute method

219
00:09:26,840 --> 00:09:29,990
to execute the SQL against the database

220
00:09:29,990 --> 00:09:31,250
and return something that behaves

221
00:09:31,250 --> 00:09:33,090
very much like a list.

222
00:09:33,090 --> 00:09:35,590
So we can iterate over it to process each row,

223
00:09:35,590 --> 00:09:38,480
but it's really not a list.

224
00:09:38,480 --> 00:09:40,860
And if you think about it, a database table

225
00:09:40,860 --> 00:09:43,670
could contain, you know, literally billions of rows.

226
00:09:43,670 --> 00:09:45,520
So if the cursor tried to load them all

227
00:09:45,520 --> 00:09:47,440
into a list in memory,

228
00:09:47,440 --> 00:09:50,410
it's highly likely we'd run out of memory.

229
00:09:50,410 --> 00:09:53,040
So a cursor is what's called a generator.

230
00:09:53,040 --> 00:09:55,860
Now, I'm not gonna go into detail about those now,

231
00:09:55,860 --> 00:09:58,510
but a generator is basically an iterable

232
00:09:58,510 --> 00:10:01,070
that works by generating the next value

233
00:10:01,070 --> 00:10:03,750
each time it's used in Python.

234
00:10:03,750 --> 00:10:06,100
You can create an iterable object

235
00:10:06,100 --> 00:10:09,790
that will return every single possible integer number.

236
00:10:09,790 --> 00:10:11,010
So you could count to infinity

237
00:10:11,010 --> 00:10:12,430
without running out of memory.

238
00:10:12,430 --> 00:10:14,280
Time may be against you, of course,

239
00:10:14,280 --> 00:10:16,880
but memory wouldn't be a problem.

240
00:10:16,880 --> 00:10:20,210
So when our code iterates over the cursor,

241
00:10:20,210 --> 00:10:22,330
it returns the next row from the database

242
00:10:22,330 --> 00:10:25,270
but doesn't actually keep track of previous rows.

243
00:10:25,270 --> 00:10:27,330
Now because it's not really a list,

244
00:10:27,330 --> 00:10:29,800
there's no way to go back to previous records,

245
00:10:29,800 --> 00:10:32,630
and that explains why this next bit of code

246
00:10:32,630 --> 00:10:35,080
doesn't do what we might expect.

247
00:10:35,080 --> 00:10:36,000
And to show you what I mean,

248
00:10:36,000 --> 00:10:39,270
I'm going to actually take a copy of our for loop

249
00:10:39,270 --> 00:10:41,580
up to and including the separator,

250
00:10:41,580 --> 00:10:45,300
and I'm gonna paste that down here,

251
00:10:45,300 --> 00:10:46,760
put another space there.

252
00:10:46,760 --> 00:10:48,260
So looking at this, this, well actually,

253
00:10:48,260 --> 00:10:50,260
let's just run it first.

254
00:10:51,960 --> 00:10:53,020
So it's looking at the output

255
00:10:53,020 --> 00:10:56,090
at the bottom of the screen there.

256
00:10:56,090 --> 00:10:59,170
You may have expected the rows to be printed out again,

257
00:10:59,170 --> 00:11:01,190
but when we get to the second for loop,

258
00:11:01,190 --> 00:11:04,390
the cursors actually run out of rows, so nothing's printed.

259
00:11:04,390 --> 00:11:06,760
The only way to get our cursor to start again

260
00:11:06,760 --> 00:11:09,140
is to actually run the query again.

261
00:11:09,140 --> 00:11:12,270
And what that does, it makes cursors very efficient

262
00:11:12,270 --> 00:11:14,250
when reading data from databases,

263
00:11:14,250 --> 00:11:15,620
because they don't use loads of memory

264
00:11:15,620 --> 00:11:17,510
storing all the records.

265
00:11:17,510 --> 00:11:18,800
Now, sometimes, you may actually want

266
00:11:18,800 --> 00:11:20,940
the entire dataset in a single list,

267
00:11:20,940 --> 00:11:22,340
and rather than using a for loop

268
00:11:22,340 --> 00:11:23,490
to build up your own list,

269
00:11:23,490 --> 00:11:26,480
you can actually use the fetchall method.

270
00:11:26,480 --> 00:11:27,530
All right, so I'm actually gonna delete

271
00:11:27,530 --> 00:11:29,770
that second for loop,

272
00:11:29,770 --> 00:11:32,220
'cause it's not actually doing anything.

273
00:11:32,220 --> 00:11:35,090
And let's actually go above that, that loop.

274
00:11:35,090 --> 00:11:37,400
We'll actually put a space here, actually,

275
00:11:37,400 --> 00:11:39,210
after the execute, anyway, to just

276
00:11:39,210 --> 00:11:40,830
free things up a little bit.

277
00:11:40,830 --> 00:11:42,980
But let's actually just add something to that again,

278
00:11:42,980 --> 00:11:45,480
and put print cursor.fetchall.

279
00:11:51,470 --> 00:11:54,890
All right, so now if I actually run this,

280
00:11:56,860 --> 00:11:59,220
you can see that the fetchall has returned a list

281
00:11:59,220 --> 00:12:02,570
containing a tuple for each row in the database.

282
00:12:02,570 --> 00:12:04,070
So it is possible to get all the rows

283
00:12:04,070 --> 00:12:05,980
from a database into a list,

284
00:12:05,980 --> 00:12:08,130
and then you can actually move backwards and forwards

285
00:12:08,130 --> 00:12:10,180
through the items in the list.

286
00:12:10,180 --> 00:12:11,430
Because all the data's being retrieved

287
00:12:11,430 --> 00:12:13,620
from the cursor by the fetchall method,

288
00:12:13,620 --> 00:12:16,730
our for loop, though, in this particular case, on line 13,

289
00:12:16,730 --> 00:12:18,650
hasn't got anything to print.

290
00:12:18,650 --> 00:12:20,330
Now, there's also a fetchone method

291
00:12:20,330 --> 00:12:23,460
that returns the next row in the cursor.

292
00:12:23,460 --> 00:12:24,510
And to get that to work,

293
00:12:24,510 --> 00:12:26,910
we'll have to come in out the call the fetchall.

294
00:12:26,910 --> 00:12:28,670
So we'll do that first.

295
00:12:28,670 --> 00:12:32,400
And then we can actually change our code a little bit,

296
00:12:32,400 --> 00:12:36,240
up here, and we can put print cursor.fetchone.

297
00:12:40,220 --> 00:12:42,980
Let's just duplicate that another two times.

298
00:12:42,980 --> 00:12:45,320
And if we actually run this,

299
00:12:46,690 --> 00:12:48,300
so you can see what happened there.

300
00:12:48,300 --> 00:12:51,000
The first two times, it returned what was the current row,

301
00:12:51,000 --> 00:12:52,470
then moved on to the next one,

302
00:12:52,470 --> 00:12:56,470
but the third call, call to fetchone, results in none,

303
00:12:56,470 --> 00:12:59,320
and that's because there's no rows left to fetch.

304
00:12:59,320 --> 00:13:01,410
So fetchone is quite useful,

305
00:13:01,410 --> 00:13:03,200
and we're gonna be using that a bit later,

306
00:13:03,200 --> 00:13:05,150
when we wanna retrieve a single row

307
00:13:05,150 --> 00:13:06,790
based on its ID.

308
00:13:06,790 --> 00:13:09,010
All right, so I'm gonna finish the video here now.

309
00:13:09,010 --> 00:13:10,510
In the next video, we're gonna look at that shortcut

310
00:13:10,510 --> 00:13:12,560
that I mentioned earlier in this video,

311
00:13:12,560 --> 00:13:14,350
so I'll see you in the next video.

