1
00:00:05,270 --> 00:00:08,940
In the previous video we got our code writing data to the database.

2
00:00:08,940 --> 00:00:12,280
Next we're going to look at how to get the data back out again. To do that,

3
00:00:12,300 --> 00:00:18,180
we're going to use a cursor. In database terms a cursor allows us to access individual records in the

4
00:00:18,180 --> 00:00:19,260
database.

5
00:00:19,260 --> 00:00:25,150
We can move backwards and forwards in the cursor, and it takes care of retrieving the rows for us. Once

6
00:00:25,430 --> 00:00:27,550
we position the cursor at a particular row,

7
00:00:27,720 --> 00:00:32,640
we can then use it to read the individual columns or fields of data.

8
00:00:32,640 --> 00:00:33,870
Now you'll often use a cursor

9
00:00:33,930 --> 00:00:39,000
even if you only expect to get a single row back from a query. You don't have to worry about how many

10
00:00:39,000 --> 00:00:45,240
rows will be retrieved. They're all accessed via the database cursor. Your database query could return

11
00:00:45,240 --> 00:00:51,060
thousands of rows, and that could be a problem because smart phones have limited amounts of memory. All

12
00:00:51,060 --> 00:00:55,050
that data possibly wouldn't fit in the memory we've got available,

13
00:00:55,050 --> 00:00:59,620
but a cursor takes care of this and points to just a single row at a time.

14
00:00:59,820 --> 00:01:03,880
So we can access and manipulate the data without having to load it all into memory,

15
00:01:04,220 --> 00:01:09,600
and this avoids the performance issues of having to retrieve thousands of records into memory. A cursor

16
00:01:09,600 --> 00:01:14,370
enables us to manipulate the data, but only retrieves it one record at a time,

17
00:01:14,370 --> 00:01:16,700
as you'll see when we start writing our code.

18
00:01:17,070 --> 00:01:20,270
So Android comes with a cursor class built in so we can use that.

19
00:01:20,280 --> 00:01:21,440
So let's give that a go now.

20
00:01:21,680 --> 00:01:25,010
What I'm going to do is come down here, after our

21
00:01:25,020 --> 00:01:29,970
last statement we added which was the val generatedId for the database insert. And I'm going to type val

22
00:01:30,570 --> 00:01:40,120
query is equal to database.rawQuery, and in parentheses and double quotes,

23
00:01:40,230 --> 00:01:45,390
SELECT * FROM contacts.

24
00:01:45,780 --> 00:01:53,990
Then the second argument, we're going to pass null to it. The rawQuery method returns a cursor. The first parameter's

25
00:01:54,020 --> 00:01:59,740
the SQL query that we want to use to retrieve the data, and I've set the second argument to null.

26
00:01:59,750 --> 00:02:03,230
Now if you want to know what the second argument is let's have a look at the documentation,

27
00:02:06,180 --> 00:02:09,580
and you can see there that second argument is the selectionArgs.

28
00:02:09,860 --> 00:02:16,910
This provides values that we can include in a WHERE clause to our SQL query, or into our SQL query, and we'll

29
00:02:16,910 --> 00:02:18,550
have a look at that a little bit later.

30
00:02:18,590 --> 00:02:21,750
For now I've just set that to null. And by the way, with these windows,

31
00:02:22,370 --> 00:02:27,440
these documentation windows, they often contain more text than will fit in them, and they always

32
00:02:27,440 --> 00:02:32,070
seem to start off the same size when you first open one, regardless of their contents.

33
00:02:32,090 --> 00:02:36,500
So make sure you either resize them or scroll down, so that you get to see all the information.

34
00:02:36,590 --> 00:02:40,050
In this case the information didn't require me to scroll.

35
00:02:40,390 --> 00:02:45,660
And by the way, we can also see that if we have a look at the return information for rawQuery,

36
00:02:45,770 --> 00:02:50,090
we can see that it's a cursor object positioned before the first record.

37
00:02:50,340 --> 00:02:53,390
It tells us here that it's positioned before the first entry.

38
00:02:53,690 --> 00:02:58,970
Another thing to note there is the SQL string must not be semi-colon terminated, as you would

39
00:02:58,970 --> 00:03:02,420
normally do when you're creating SQL source code or

40
00:03:02,420 --> 00:03:06,710
what you've done earlier in this section of the course, when using a sqlite3 command

41
00:03:06,710 --> 00:03:08,820
line, program.

42
00:03:09,160 --> 00:03:15,920
Alright, so that's rawQuery. There's also a query method as well, or several query methods to be precise, and they

43
00:03:15,920 --> 00:03:20,800
allow you to specify ORDER BY clauses, as well as more filtering and grouping.

44
00:03:21,170 --> 00:03:25,250
And it's definitely worth checking those methods out when you come to write your own apps.

45
00:03:25,310 --> 00:03:30,570
We're going to be using something similar later, and you'll understand what the various arguments are

46
00:03:30,590 --> 00:03:35,230
once we've done that. But I'm using rawQuery here just to keep things simple.

47
00:03:35,420 --> 00:03:40,700
Now at the moment actually, if I hover over that, you notice that we've got this warning from Android Studio that this

48
00:03:40,700 --> 00:03:45,960
cursor should be freed up after use with close, hash close.

49
00:03:45,980 --> 00:03:50,780
Now if you're familiar with Java you'd probably use a try with resources to achieve that.

50
00:03:50,780 --> 00:03:56,180
More importantly if you're converting Java code that uses try with resources, you may struggle to do

51
00:03:56,180 --> 00:03:57,190
that in Kotlin.

52
00:03:57,470 --> 00:04:02,450
And that's because Kotlin doesn't use the same syntax as Java, and there isn't actually a try with resources

53
00:04:02,450 --> 00:04:04,480
syntax as such in Kotlin.

54
00:04:04,700 --> 00:04:09,280
Instead Kotlin provides the use function to achieve the same thing.

55
00:04:09,320 --> 00:04:12,430
So let's just type a bit of code and then we'll check out the documentation.

56
00:04:12,560 --> 00:04:15,400
So it's query.use, and

57
00:04:16,399 --> 00:04:18,800
notice that it's adding a code block after that, and

58
00:04:18,829 --> 00:04:25,970
we'll have a look at the documentation for use. Basically, it executes the given block function on this resource

59
00:04:26,330 --> 00:04:29,040
and then closes it down correctly.

60
00:04:29,060 --> 00:04:33,210
So in this case it'll close the cursor, whether or not an exception is thrown.

61
00:04:33,590 --> 00:04:40,520
So you can use the use function with any closeable object, in the same way that Java allows try with resources

62
00:04:40,520 --> 00:04:43,810
to be used with any closeable object.

63
00:04:43,870 --> 00:04:45,010
Alright, so back in our code now.

64
00:04:46,190 --> 00:04:51,000
I'm going to put all the code to deal with our cursor inside that block.

65
00:04:51,040 --> 00:04:57,440
Now inside the code block that we've added here, we refer to the object that was called on it as it, and you can see

66
00:04:57,440 --> 00:04:59,720
that IntelliJ helpfully tells us that as well - 

67
00:04:59,840 --> 00:05:00,790
it:Cursor.

68
00:05:01,090 --> 00:05:05,370
It's adding that for us as a reminder of what you need to do there.

69
00:05:06,060 --> 00:05:07,940
So to write the code we'll do something like:

70
00:05:07,970 --> 00:05:15,140
if, this is in the code block, parentheses it.moveToFirst.

71
00:05:15,230 --> 00:05:20,480
So again, the reason that we're using it and we're not using query here, is that we're referring

72
00:05:20,480 --> 00:05:22,040
to the object that it was called on

73
00:05:22,040 --> 00:05:25,900
as it. And that's why we've got it.moveToFirst here rather than query -

74
00:05:25,930 --> 00:05:27,110
dot moveToFirst.

75
00:05:27,390 --> 00:05:31,490
Query is a cursor, and we're telling it to move to the first record.

76
00:05:31,550 --> 00:05:37,220
Now it's actually quite possible that our sequel query didn't return any records. In which case, the moveTo

77
00:05:37,220 --> 00:05:39,260
First method would return false.

78
00:05:39,350 --> 00:05:44,880
So that's why we're checking that it did manage to move to the first record before we do any more processing.

79
00:05:44,880 --> 00:05:47,150
And just to confirm that if you want to check that.

80
00:05:47,180 --> 00:05:50,550
Have a look at the documentation for moveToFirst, and you can see

81
00:05:50,980 --> 00:05:56,030
it tells us there specifically that this method will return false if the cursor is empty.

82
00:05:56,330 --> 00:06:01,130
So OK, so if it returns true then the cursor's positioned at the first record and we can start reading the

83
00:06:01,130 --> 00:06:01,740
data.

84
00:06:01,940 --> 00:06:03,920
So let's put some code in that code block,

85
00:06:04,160 --> 00:06:07,700
knowing that at this point we guaranteed to have at least one record.

86
00:06:07,740 --> 00:06:10,010
So I'll put a comment here that we're going to "Cycle through all the records"

87
00:06:17,910 --> 00:06:22,800
with parentheses query, and by the way we aren't yet cycling through all records. I'm about to do that a little

88
00:06:22,800 --> 00:06:33,420
bit later, but for now though we're going to query a single record using with query. Then within the with query cold block we'll put

89
00:06:33,580 --> 00:06:45,190
val id equals getLong parentheses zero, val name equals getString parentheses 1, val phone equals get

90
00:06:45,190 --> 00:06:49,550
Int 2, and val email 

91
00:06:49,720 --> 00:06:54,930
equals getString 3. So again, we're not cycling through all the records yet.

92
00:06:54,930 --> 00:06:55,800
We're going to do that in a minute,

93
00:06:55,800 --> 00:06:56,970
hence the comment.

94
00:06:57,180 --> 00:07:00,670
For now though we're just reading the values for the first record.

95
00:07:00,810 --> 00:07:06,140
Now note that we're using the get methods which need the index of a column and a table, and obviously it's

96
00:07:06,250 --> 00:07:06,540
get

97
00:07:06,560 --> 00:07:08,840
and then the type of data.

98
00:07:09,020 --> 00:07:10,730
So we've got a long here, we've got a

99
00:07:10,740 --> 00:07:12,270
string here, we've got an int here,

100
00:07:12,300 --> 00:07:12,990
etc.

101
00:07:13,560 --> 00:07:19,180
So these, all of these functions need an index of the column and the table. So remember that computers

102
00:07:19,180 --> 00:07:21,650
index the first item as index 0,

103
00:07:21,900 --> 00:07:27,050
so that's why we're reading the first column into ID, the second into name, the third into phone and

104
00:07:27,060 --> 00:07:32,600
the last into email. And the ID is a long value where its name and email are strings, and because

105
00:07:32,630 --> 00:07:34,610
we've stored the phone number as an integer,

106
00:07:34,750 --> 00:07:37,960
we're using getInt rather than getString but it works the same.

107
00:07:38,130 --> 00:07:42,360
In reality we really shouldn't have used an integer for the phone number, but I just wanted to show you

108
00:07:42,360 --> 00:07:44,760
how to retrieve different types of data.

109
00:07:45,210 --> 00:07:49,830
And that's also what I meant in an earlier video when I warned about SQLite columns not really

110
00:07:49,830 --> 00:07:51,170
having a data type.

111
00:07:51,210 --> 00:07:55,680
There's nothing to prevent us from storing a string in the phone field, but that would break out Kotlin

112
00:07:55,700 --> 00:07:58,070
code when it tried to read an int.

113
00:07:58,210 --> 00:07:58,520
Alright.

114
00:07:58,530 --> 00:08:02,980
So for our simple example, we're going to display the data in the logcat.

115
00:08:03,010 --> 00:08:04,170
So what I'm trying to do,

116
00:08:05,760 --> 00:08:11,340
is below the lines that retrieve the data, I'm going to type val

117
00:08:11,340 --> 00:08:15,120
result equals, then double quotes,

118
00:08:15,200 --> 00:08:27,090
ID colon $id Name equals $name phone equals $phone and email equals $email.

119
00:08:28,510 --> 00:08:30,990
Then I'm going to type Log.d parentheses

120
00:08:31,150 --> 00:08:43,480
TAG comma onCreate colon reading data $result, and you can see that IntelliJ is helpfully

121
00:08:43,500 --> 00:08:49,800
telling us that this is all attached to the With that we've actually set up for this query and the appropriate

122
00:08:49,800 --> 00:08:58,540
code block. Alright so finally, the other thing we want to do here now is we want to close the database. So database.close, so calling

123
00:08:58,590 --> 00:09:04,230
the close method. Closing the database is a good idea, but you'd normally do that when the app is closed,

124
00:09:04,650 --> 00:09:05,570
rather than here.

125
00:09:05,850 --> 00:09:10,270
That way the database is available while the app's running and you don't have to keep opening it.

126
00:09:10,360 --> 00:09:16,640
And we could also have wrapped all this code up in a database dot use block, just like we did for the cursor code.

127
00:09:16,790 --> 00:09:23,070
I didn't do that here because, as I've said, it's more usual to keep the database open until the app finishes.

128
00:09:23,070 --> 00:09:28,650
In fact if you wanted to use this basic approach in a real app, you'd probably create a separate class

129
00:09:28,650 --> 00:09:31,060
to handle all the database accesses.

130
00:09:31,440 --> 00:09:32,670
We're not going to do that.

131
00:09:32,680 --> 00:09:35,270
We're going to be using a content provider instead.

132
00:09:35,430 --> 00:09:40,370
At the moment though, we're just seeing how to run SQL statements from our Kotlin code.

133
00:09:40,470 --> 00:09:44,270
Alright so at this point in time, we're now ready to run this simple app. We're going to run it now.

134
00:09:47,700 --> 00:09:54,160
OK, I'm going to select the same one that I ran it on last, click OK. I'll just fast forward this until

135
00:09:54,160 --> 00:09:59,830
it gets to the stage of running.

136
00:09:59,890 --> 00:10:04,680
Alright so you can see we've got an error immediately. So when that happens, open

137
00:10:04,940 --> 00:10:12,020
up the logcat tab and see what we can see there, and we might have to remove the filter there so

138
00:10:12,020 --> 00:10:16,820
that we can say all the information. Also I've noticed that sometimes Android Studio continues to show

139
00:10:16,920 --> 00:10:21,900
unrelated log entries, even with Show only selected application over here to the right selected.

140
00:10:21,980 --> 00:10:25,940
If that happens just select your application again, in the second drop-down from the left,

141
00:10:25,940 --> 00:10:26,580
so this one here.

142
00:10:28,130 --> 00:10:32,780
In my case I don't need to do that. The reason I'm not seeing all the output here is because we've got /mainactivity

143
00:10:32,770 --> 00:10:38,390
still showing there. Again, I could select that again,

144
00:10:38,590 --> 00:10:44,220
and notice by doing that now it actually clears the log of all that unrelated information.

145
00:10:44,220 --> 00:10:48,610
And we're back to looking and seeing why our application crashed.

146
00:10:48,610 --> 00:10:54,610
Now one technique for reading these tech traces is to read the first bit that describes the error, then ignore

147
00:10:54,700 --> 00:10:57,130
the rest of the block - all the lines starting with at,

148
00:10:57,130 --> 00:11:04,840
in other words. Now down down up to here and have a look at this first line: table contacts already exists,

149
00:11:05,440 --> 00:11:09,340
when compiling, and it gives us the SQL that was executing.

150
00:11:09,340 --> 00:11:11,890
So that's pretty clear as to what the problem was.

151
00:11:12,330 --> 00:11:13,720
And again just to be clear though,

152
00:11:16,750 --> 00:11:21,500
you can see down here that it was caused by sqlite exceptions. So that told us fairly quickly anyway, even if we

153
00:11:21,500 --> 00:11:25,880
didn't already know, that it was complaining about the CREATE TABLE statement

154
00:11:25,880 --> 00:11:27,890
and you can see that to the right of the screen there now.

155
00:11:28,250 --> 00:11:31,700
So basically we knew that there was a sqlite exception of the code,

156
00:11:31,700 --> 00:11:36,770
so the problem was probably relating to our database code. We probably guessed that anyway because we haven't

157
00:11:36,770 --> 00:11:41,820
added any other code, but it is always useful to check these logs just to make sure that's the case.

158
00:11:42,200 --> 00:11:44,980
So basically the sqlite

159
00:11:45,320 --> 00:11:48,270
exception is complaining about the CREATE TABLE statement.

160
00:11:48,440 --> 00:11:53,750
And if we skip to the next block, eventually we see some code here that we can click. Anything in blue

161
00:11:53,750 --> 00:11:59,090
is the code that we've been working on, so we can click on that to navigate to the line of code that

162
00:11:59,090 --> 00:12:04,730
is actually causing the problem. And you can see that that's the line that caused the execSQLs method, which

163
00:12:04,740 --> 00:12:08,920
means the problem's going to be in the SQL statement a couple of lines further up -

164
00:12:08,990 --> 00:12:10,950
line 24 in fact.

165
00:12:11,330 --> 00:12:16,120
Basically the table contacts already exists and that's why we're getting that crash.

166
00:12:16,130 --> 00:12:20,930
Now fortunately while testing, there's an easy way to fix that. We can just come up here and change the

167
00:12:20,930 --> 00:12:22,510
SQL code slightly

168
00:12:22,760 --> 00:12:30,220
and add the words IF NOT EXISTS after the CREATE TABLE statement. So CREATE TABLE IF NOT EXISTS.

169
00:12:30,720 --> 00:12:35,650
contacts. So in other words, the table won't be attempted to be recreated

170
00:12:35,870 --> 00:12:37,240
if it's already found.

171
00:12:37,330 --> 00:12:39,200
So I'm just going to click on and run,

172
00:12:42,090 --> 00:12:47,910
close logcat for now. And we'll just go back and check our app. This time our app has worked.

173
00:12:47,920 --> 00:12:50,730
We haven't got a crash this time so that's a good sign.

174
00:12:50,760 --> 00:12:57,740
And we will go back to our logcat again, and we can just type /main, and we can quickly see that we've

175
00:12:57,740 --> 00:13:01,670
got some data showing on the screen there now. So it's doing what we expect.

176
00:13:01,670 --> 00:13:06,080
Well it sort of is. We get the details for the first row appearing,

177
00:13:06,230 --> 00:13:10,440
but the ID for the row that's just been created is now 4 rather than 2.

178
00:13:10,800 --> 00:13:15,310
And that's because our code keeps adding those two records every time we run it.

179
00:13:15,320 --> 00:13:19,530
Now normally you'd be adding new rows when the user does something, such as saving a new contact. You

180
00:13:19,580 --> 00:13:23,130
wouldn't normally run these Insert queries each time the app runs.

181
00:13:23,440 --> 00:13:25,930
And we don't want to keep adding the same two rows,

182
00:13:25,960 --> 00:13:28,750
and we can easily prevent that by dropping the table.

183
00:13:28,880 --> 00:13:34,210
Let's just make a quick change to the code to do that, and we'll add it immediately after our database is being

184
00:13:34,220 --> 00:13:35,960
defined on line 23.

185
00:13:35,990 --> 00:13:43,960
We're going to type database.execSQL, and in parentheses I'm going to type double quotes DROP TABLE

186
00:13:44,500 --> 00:13:50,990
IF EXISTS contacts. So I'm going to DROP THE TABLE every time

187
00:13:50,990 --> 00:13:53,700
IF it EXISTS. Let's actually run that again,

188
00:13:55,960 --> 00:13:57,500
and confirm that that works.

189
00:14:00,660 --> 00:14:05,310
This time you can see we've got record added with id 2, and that confirms that the table was dropped

190
00:14:05,400 --> 00:14:08,400
immediately after we got access to the database object.

191
00:14:08,450 --> 00:14:13,620
Now generally I prefer to put the SQL statements into a string variable like I did for the CREATE TABLE

192
00:14:13,620 --> 00:14:15,160
on line 25.

193
00:14:15,210 --> 00:14:20,260
This makes it easier to log the SQL which makes debugging easier if you make a mistake.

194
00:14:20,640 --> 00:14:23,490
You can just include the SQL as a string as we're doing here.

195
00:14:23,780 --> 00:14:29,200
But I do recommend using a variable and logging it's value, especially while developing your app.

196
00:14:29,250 --> 00:14:31,920
You can always delete the logging later once the app's working.

197
00:14:31,920 --> 00:14:37,020
Also be aware that these debug logging commands are stripped out by the build system when you create

198
00:14:37,020 --> 00:14:42,630
the release version of your app. Basically when you use Log.d, the logging lines are removed automatically

199
00:14:43,080 --> 00:14:45,730
so they won't affect your apps performance.

200
00:14:45,740 --> 00:14:48,910
Alright so there's one last change to make before we stop this video.

201
00:14:49,290 --> 00:14:56,520
We can loop through all the rows in the cursor by using moveToNext instead of moveToFirst. Remember

202
00:14:56,520 --> 00:14:59,350
that the cursor's positioned before the first record,

203
00:14:59,400 --> 00:15:06,130
and that means that moveToNext will do the same thing as moveToFirst, the first time it's used.

204
00:15:06,150 --> 00:15:09,260
So let's go ahead and make a simple change to our code to check that.

205
00:15:09,330 --> 00:15:11,690
So I'm going to close down logcat first.

206
00:15:11,970 --> 00:15:18,190
And the change we want to make here - at the moment we've got an if statement here on line 49. I'm going to change the

207
00:15:18,220 --> 00:15:22,840
if to while. I'm creating a while loop

208
00:15:22,850 --> 00:15:28,680
now instead, and I'm going to change this code here, or rather I'm going to remove some of this now, because we in fact

209
00:15:28,680 --> 00:15:32,460
have added the code now to cycle through all records.

210
00:15:32,460 --> 00:15:36,210
So now when we run this we should find that we've got two entries showing on the screen, so let's run

211
00:15:36,210 --> 00:15:38,570
this. Stop the app and run it again, and we'll bring up logcat.

212
00:15:42,830 --> 00:15:44,120
Let's have a look and see what it gives us. And obviously I've

213
00:15:47,560 --> 00:15:50,840
made a mistake there so what I'm going to do is just stop that,

214
00:15:50,840 --> 00:15:58,380
stop our app. And you can see what I've done there. I basically didn't change this properly. I put while it.move

215
00:15:58,380 --> 00:15:59,600
ToFirst.

216
00:15:59,600 --> 00:16:05,280
So it always continually cycled back to the first record, so that therefore the while statement never became

217
00:16:05,280 --> 00:16:05,670
false and

218
00:16:05,670 --> 00:16:07,150
we never exited the loop.

219
00:16:07,190 --> 00:16:09,000
And of course I talked about it but we didn't do it.

220
00:16:09,030 --> 00:16:13,700
We need to add a moveToNext,

221
00:16:13,850 --> 00:16:16,590
bearing in mind that with moveToNext,

222
00:16:16,730 --> 00:16:21,150
it does the same thing as moveToFirst, the first time it's used. So it'll move to the first record, then

223
00:16:21,160 --> 00:16:23,630
automatically progress through to the next record and so on.

224
00:16:23,840 --> 00:16:24,800
Let's run it again,

225
00:16:25,040 --> 00:16:27,370
and we should find this time we'll see both records.

226
00:16:30,150 --> 00:16:35,770
This time you can see now, we've got reading data ID 1 and ID 2, and clearly the values are different

227
00:16:35,770 --> 00:16:37,150
there on the screen as well.

228
00:16:37,210 --> 00:16:42,590
Basically the logcat's showing both records correctly and our very simple app's working fine.

229
00:16:43,060 --> 00:16:49,000
So this is an incredibly basic app, but we've seen how to create a database using the SQLite

230
00:16:49,300 --> 00:16:50,700
database class.

231
00:16:50,740 --> 00:16:56,980
We then created a table and inserted records by executing the appropriate SQL statements.

232
00:16:57,000 --> 00:17:01,540
Now I've said several times that you wouldn't write a real app this way. At the very least you'd create

233
00:17:01,540 --> 00:17:04,119
a class to handle all the database access.

234
00:17:04,150 --> 00:17:08,329
You'd also want to make sure that your query isn't performed on the main thread.

235
00:17:08,500 --> 00:17:11,880
That's not a good idea because database operations can be slow.

236
00:17:12,050 --> 00:17:16,619
Now there are ways to handle this using things like content providers and cursor loaders, and we're

237
00:17:16,780 --> 00:17:18,550
going to be looking at both of those.

238
00:17:18,550 --> 00:17:23,640
But the basics of executing SQL statements from Kotlin code will still be needed.

239
00:17:23,650 --> 00:17:24,720
Now we know how to do that,

240
00:17:24,730 --> 00:17:29,320
we're ready to look at more suitable ways of dealing with databases. In the next video though, we're going to

241
00:17:29,320 --> 00:17:35,920
have a look at where our database is stored on the device, so that we can open it using the sqlite command

242
00:17:35,920 --> 00:17:41,350
line, and check that it's been set up correctly. When debugging, it's very useful to be able to examine

243
00:17:41,350 --> 00:17:44,130
the data that's been stored in your database.

244
00:17:44,140 --> 00:17:47,680
So in the next video we'll find out how to do just that.

245
00:17:47,680 --> 00:17:48,940
See you in the next video.

